18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2013 Red Hat
48c2ecf20Sopenharmony_ci * Author: Rob Clark <robdclark@gmail.com>
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * Copyright (c) 2014 The Linux Foundation. All rights reserved.
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include "a3xx_gpu.h"
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#define A3XX_INT0_MASK \
128c2ecf20Sopenharmony_ci	(A3XX_INT0_RBBM_AHB_ERROR |        \
138c2ecf20Sopenharmony_ci	 A3XX_INT0_RBBM_ATB_BUS_OVERFLOW | \
148c2ecf20Sopenharmony_ci	 A3XX_INT0_CP_T0_PACKET_IN_IB |    \
158c2ecf20Sopenharmony_ci	 A3XX_INT0_CP_OPCODE_ERROR |       \
168c2ecf20Sopenharmony_ci	 A3XX_INT0_CP_RESERVED_BIT_ERROR | \
178c2ecf20Sopenharmony_ci	 A3XX_INT0_CP_HW_FAULT |           \
188c2ecf20Sopenharmony_ci	 A3XX_INT0_CP_IB1_INT |            \
198c2ecf20Sopenharmony_ci	 A3XX_INT0_CP_IB2_INT |            \
208c2ecf20Sopenharmony_ci	 A3XX_INT0_CP_RB_INT |             \
218c2ecf20Sopenharmony_ci	 A3XX_INT0_CP_REG_PROTECT_FAULT |  \
228c2ecf20Sopenharmony_ci	 A3XX_INT0_CP_AHB_ERROR_HALT |     \
238c2ecf20Sopenharmony_ci	 A3XX_INT0_CACHE_FLUSH_TS |        \
248c2ecf20Sopenharmony_ci	 A3XX_INT0_UCHE_OOB_ACCESS)
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ciextern bool hang_debug;
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_cistatic void a3xx_dump(struct msm_gpu *gpu);
298c2ecf20Sopenharmony_cistatic bool a3xx_idle(struct msm_gpu *gpu);
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_cistatic void a3xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
328c2ecf20Sopenharmony_ci{
338c2ecf20Sopenharmony_ci	struct msm_drm_private *priv = gpu->dev->dev_private;
348c2ecf20Sopenharmony_ci	struct msm_ringbuffer *ring = submit->ring;
358c2ecf20Sopenharmony_ci	unsigned int i;
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci	for (i = 0; i < submit->nr_cmds; i++) {
388c2ecf20Sopenharmony_ci		switch (submit->cmd[i].type) {
398c2ecf20Sopenharmony_ci		case MSM_SUBMIT_CMD_IB_TARGET_BUF:
408c2ecf20Sopenharmony_ci			/* ignore IB-targets */
418c2ecf20Sopenharmony_ci			break;
428c2ecf20Sopenharmony_ci		case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
438c2ecf20Sopenharmony_ci			/* ignore if there has not been a ctx switch: */
448c2ecf20Sopenharmony_ci			if (priv->lastctx == submit->queue->ctx)
458c2ecf20Sopenharmony_ci				break;
468c2ecf20Sopenharmony_ci			fallthrough;
478c2ecf20Sopenharmony_ci		case MSM_SUBMIT_CMD_BUF:
488c2ecf20Sopenharmony_ci			OUT_PKT3(ring, CP_INDIRECT_BUFFER_PFD, 2);
498c2ecf20Sopenharmony_ci			OUT_RING(ring, lower_32_bits(submit->cmd[i].iova));
508c2ecf20Sopenharmony_ci			OUT_RING(ring, submit->cmd[i].size);
518c2ecf20Sopenharmony_ci			OUT_PKT2(ring);
528c2ecf20Sopenharmony_ci			break;
538c2ecf20Sopenharmony_ci		}
548c2ecf20Sopenharmony_ci	}
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci	OUT_PKT0(ring, REG_AXXX_CP_SCRATCH_REG2, 1);
578c2ecf20Sopenharmony_ci	OUT_RING(ring, submit->seqno);
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	/* Flush HLSQ lazy updates to make sure there is nothing
608c2ecf20Sopenharmony_ci	 * pending for indirect loads after the timestamp has
618c2ecf20Sopenharmony_ci	 * passed:
628c2ecf20Sopenharmony_ci	 */
638c2ecf20Sopenharmony_ci	OUT_PKT3(ring, CP_EVENT_WRITE, 1);
648c2ecf20Sopenharmony_ci	OUT_RING(ring, HLSQ_FLUSH);
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	/* wait for idle before cache flush/interrupt */
678c2ecf20Sopenharmony_ci	OUT_PKT3(ring, CP_WAIT_FOR_IDLE, 1);
688c2ecf20Sopenharmony_ci	OUT_RING(ring, 0x00000000);
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci	/* BIT(31) of CACHE_FLUSH_TS triggers CACHE_FLUSH_TS IRQ from GPU */
718c2ecf20Sopenharmony_ci	OUT_PKT3(ring, CP_EVENT_WRITE, 3);
728c2ecf20Sopenharmony_ci	OUT_RING(ring, CACHE_FLUSH_TS | BIT(31));
738c2ecf20Sopenharmony_ci	OUT_RING(ring, rbmemptr(ring, fence));
748c2ecf20Sopenharmony_ci	OUT_RING(ring, submit->seqno);
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci#if 0
778c2ecf20Sopenharmony_ci	/* Dummy set-constant to trigger context rollover */
788c2ecf20Sopenharmony_ci	OUT_PKT3(ring, CP_SET_CONSTANT, 2);
798c2ecf20Sopenharmony_ci	OUT_RING(ring, CP_REG(REG_A3XX_HLSQ_CL_KERNEL_GROUP_X_REG));
808c2ecf20Sopenharmony_ci	OUT_RING(ring, 0x00000000);
818c2ecf20Sopenharmony_ci#endif
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	adreno_flush(gpu, ring, REG_AXXX_CP_RB_WPTR);
848c2ecf20Sopenharmony_ci}
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_cistatic bool a3xx_me_init(struct msm_gpu *gpu)
878c2ecf20Sopenharmony_ci{
888c2ecf20Sopenharmony_ci	struct msm_ringbuffer *ring = gpu->rb[0];
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci	OUT_PKT3(ring, CP_ME_INIT, 17);
918c2ecf20Sopenharmony_ci	OUT_RING(ring, 0x000003f7);
928c2ecf20Sopenharmony_ci	OUT_RING(ring, 0x00000000);
938c2ecf20Sopenharmony_ci	OUT_RING(ring, 0x00000000);
948c2ecf20Sopenharmony_ci	OUT_RING(ring, 0x00000000);
958c2ecf20Sopenharmony_ci	OUT_RING(ring, 0x00000080);
968c2ecf20Sopenharmony_ci	OUT_RING(ring, 0x00000100);
978c2ecf20Sopenharmony_ci	OUT_RING(ring, 0x00000180);
988c2ecf20Sopenharmony_ci	OUT_RING(ring, 0x00006600);
998c2ecf20Sopenharmony_ci	OUT_RING(ring, 0x00000150);
1008c2ecf20Sopenharmony_ci	OUT_RING(ring, 0x0000014e);
1018c2ecf20Sopenharmony_ci	OUT_RING(ring, 0x00000154);
1028c2ecf20Sopenharmony_ci	OUT_RING(ring, 0x00000001);
1038c2ecf20Sopenharmony_ci	OUT_RING(ring, 0x00000000);
1048c2ecf20Sopenharmony_ci	OUT_RING(ring, 0x00000000);
1058c2ecf20Sopenharmony_ci	OUT_RING(ring, 0x00000000);
1068c2ecf20Sopenharmony_ci	OUT_RING(ring, 0x00000000);
1078c2ecf20Sopenharmony_ci	OUT_RING(ring, 0x00000000);
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci	adreno_flush(gpu, ring, REG_AXXX_CP_RB_WPTR);
1108c2ecf20Sopenharmony_ci	return a3xx_idle(gpu);
1118c2ecf20Sopenharmony_ci}
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_cistatic int a3xx_hw_init(struct msm_gpu *gpu)
1148c2ecf20Sopenharmony_ci{
1158c2ecf20Sopenharmony_ci	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
1168c2ecf20Sopenharmony_ci	struct a3xx_gpu *a3xx_gpu = to_a3xx_gpu(adreno_gpu);
1178c2ecf20Sopenharmony_ci	uint32_t *ptr, len;
1188c2ecf20Sopenharmony_ci	int i, ret;
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	DBG("%s", gpu->name);
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci	if (adreno_is_a305(adreno_gpu)) {
1238c2ecf20Sopenharmony_ci		/* Set up 16 deep read/write request queues: */
1248c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF0, 0x10101010);
1258c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF1, 0x10101010);
1268c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_OUT_RD_LIM_CONF0, 0x10101010);
1278c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_OUT_WR_LIM_CONF0, 0x10101010);
1288c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303);
1298c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF0, 0x10101010);
1308c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF1, 0x10101010);
1318c2ecf20Sopenharmony_ci		/* Enable WR-REQ: */
1328c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x0000ff);
1338c2ecf20Sopenharmony_ci		/* Set up round robin arbitration between both AXI ports: */
1348c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_ARB_CTL, 0x00000030);
1358c2ecf20Sopenharmony_ci		/* Set up AOOO: */
1368c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000003c);
1378c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO, 0x003c003c);
1388c2ecf20Sopenharmony_ci	} else if (adreno_is_a306(adreno_gpu)) {
1398c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0003);
1408c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_OUT_RD_LIM_CONF0, 0x0000000a);
1418c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_OUT_WR_LIM_CONF0, 0x0000000a);
1428c2ecf20Sopenharmony_ci	} else if (adreno_is_a320(adreno_gpu)) {
1438c2ecf20Sopenharmony_ci		/* Set up 16 deep read/write request queues: */
1448c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF0, 0x10101010);
1458c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF1, 0x10101010);
1468c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_OUT_RD_LIM_CONF0, 0x10101010);
1478c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_OUT_WR_LIM_CONF0, 0x10101010);
1488c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303);
1498c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF0, 0x10101010);
1508c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF1, 0x10101010);
1518c2ecf20Sopenharmony_ci		/* Enable WR-REQ: */
1528c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x0000ff);
1538c2ecf20Sopenharmony_ci		/* Set up round robin arbitration between both AXI ports: */
1548c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_ARB_CTL, 0x00000030);
1558c2ecf20Sopenharmony_ci		/* Set up AOOO: */
1568c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000003c);
1578c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO, 0x003c003c);
1588c2ecf20Sopenharmony_ci		/* Enable 1K sort: */
1598c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT, 0x000000ff);
1608c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT_CONF, 0x000000a4);
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci	} else if (adreno_is_a330v2(adreno_gpu)) {
1638c2ecf20Sopenharmony_ci		/*
1648c2ecf20Sopenharmony_ci		 * Most of the VBIF registers on 8974v2 have the correct
1658c2ecf20Sopenharmony_ci		 * values at power on, so we won't modify those if we don't
1668c2ecf20Sopenharmony_ci		 * need to
1678c2ecf20Sopenharmony_ci		 */
1688c2ecf20Sopenharmony_ci		/* Enable 1k sort: */
1698c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT, 0x0001003f);
1708c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT_CONF, 0x000000a4);
1718c2ecf20Sopenharmony_ci		/* Enable WR-REQ: */
1728c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x00003f);
1738c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303);
1748c2ecf20Sopenharmony_ci		/* Set up VBIF_ROUND_ROBIN_QOS_ARB: */
1758c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0003);
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci	} else if (adreno_is_a330(adreno_gpu)) {
1788c2ecf20Sopenharmony_ci		/* Set up 16 deep read/write request queues: */
1798c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF0, 0x18181818);
1808c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF1, 0x18181818);
1818c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_OUT_RD_LIM_CONF0, 0x18181818);
1828c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_OUT_WR_LIM_CONF0, 0x18181818);
1838c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303);
1848c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF0, 0x18181818);
1858c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF1, 0x18181818);
1868c2ecf20Sopenharmony_ci		/* Enable WR-REQ: */
1878c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x00003f);
1888c2ecf20Sopenharmony_ci		/* Set up round robin arbitration between both AXI ports: */
1898c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_ARB_CTL, 0x00000030);
1908c2ecf20Sopenharmony_ci		/* Set up VBIF_ROUND_ROBIN_QOS_ARB: */
1918c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0001);
1928c2ecf20Sopenharmony_ci		/* Set up AOOO: */
1938c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000003f);
1948c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO, 0x003f003f);
1958c2ecf20Sopenharmony_ci		/* Enable 1K sort: */
1968c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT, 0x0001003f);
1978c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT_CONF, 0x000000a4);
1988c2ecf20Sopenharmony_ci		/* Disable VBIF clock gating. This is to enable AXI running
1998c2ecf20Sopenharmony_ci		 * higher frequency than GPU:
2008c2ecf20Sopenharmony_ci		 */
2018c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_VBIF_CLKON, 0x00000001);
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci	} else {
2048c2ecf20Sopenharmony_ci		BUG();
2058c2ecf20Sopenharmony_ci	}
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	/* Make all blocks contribute to the GPU BUSY perf counter: */
2088c2ecf20Sopenharmony_ci	gpu_write(gpu, REG_A3XX_RBBM_GPU_BUSY_MASKED, 0xffffffff);
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci	/* Tune the hystersis counters for SP and CP idle detection: */
2118c2ecf20Sopenharmony_ci	gpu_write(gpu, REG_A3XX_RBBM_SP_HYST_CNT, 0x10);
2128c2ecf20Sopenharmony_ci	gpu_write(gpu, REG_A3XX_RBBM_WAIT_IDLE_CLOCKS_CTL, 0x10);
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci	/* Enable the RBBM error reporting bits.  This lets us get
2158c2ecf20Sopenharmony_ci	 * useful information on failure:
2168c2ecf20Sopenharmony_ci	 */
2178c2ecf20Sopenharmony_ci	gpu_write(gpu, REG_A3XX_RBBM_AHB_CTL0, 0x00000001);
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci	/* Enable AHB error reporting: */
2208c2ecf20Sopenharmony_ci	gpu_write(gpu, REG_A3XX_RBBM_AHB_CTL1, 0xa6ffffff);
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci	/* Turn on the power counters: */
2238c2ecf20Sopenharmony_ci	gpu_write(gpu, REG_A3XX_RBBM_RBBM_CTL, 0x00030000);
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci	/* Turn on hang detection - this spews a lot of useful information
2268c2ecf20Sopenharmony_ci	 * into the RBBM registers on a hang:
2278c2ecf20Sopenharmony_ci	 */
2288c2ecf20Sopenharmony_ci	gpu_write(gpu, REG_A3XX_RBBM_INTERFACE_HANG_INT_CTL, 0x00010fff);
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci	/* Enable 64-byte cacheline size. HW Default is 32-byte (0x000000E0): */
2318c2ecf20Sopenharmony_ci	gpu_write(gpu, REG_A3XX_UCHE_CACHE_MODE_CONTROL_REG, 0x00000001);
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci	/* Enable Clock gating: */
2348c2ecf20Sopenharmony_ci	if (adreno_is_a306(adreno_gpu))
2358c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xaaaaaaaa);
2368c2ecf20Sopenharmony_ci	else if (adreno_is_a320(adreno_gpu))
2378c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xbfffffff);
2388c2ecf20Sopenharmony_ci	else if (adreno_is_a330v2(adreno_gpu))
2398c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xaaaaaaaa);
2408c2ecf20Sopenharmony_ci	else if (adreno_is_a330(adreno_gpu))
2418c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xbffcffff);
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci	if (adreno_is_a330v2(adreno_gpu))
2448c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_RBBM_GPR0_CTL, 0x05515455);
2458c2ecf20Sopenharmony_ci	else if (adreno_is_a330(adreno_gpu))
2468c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_RBBM_GPR0_CTL, 0x00000000);
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci	/* Set the OCMEM base address for A330, etc */
2498c2ecf20Sopenharmony_ci	if (a3xx_gpu->ocmem.hdl) {
2508c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_RB_GMEM_BASE_ADDR,
2518c2ecf20Sopenharmony_ci			(unsigned int)(a3xx_gpu->ocmem.base >> 14));
2528c2ecf20Sopenharmony_ci	}
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci	/* Turn on performance counters: */
2558c2ecf20Sopenharmony_ci	gpu_write(gpu, REG_A3XX_RBBM_PERFCTR_CTL, 0x01);
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	/* Enable the perfcntrs that we use.. */
2588c2ecf20Sopenharmony_ci	for (i = 0; i < gpu->num_perfcntrs; i++) {
2598c2ecf20Sopenharmony_ci		const struct msm_gpu_perfcntr *perfcntr = &gpu->perfcntrs[i];
2608c2ecf20Sopenharmony_ci		gpu_write(gpu, perfcntr->select_reg, perfcntr->select_val);
2618c2ecf20Sopenharmony_ci	}
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci	gpu_write(gpu, REG_A3XX_RBBM_INT_0_MASK, A3XX_INT0_MASK);
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci	ret = adreno_hw_init(gpu);
2668c2ecf20Sopenharmony_ci	if (ret)
2678c2ecf20Sopenharmony_ci		return ret;
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci	/*
2708c2ecf20Sopenharmony_ci	 * Use the default ringbuffer size and block size but disable the RPTR
2718c2ecf20Sopenharmony_ci	 * shadow
2728c2ecf20Sopenharmony_ci	 */
2738c2ecf20Sopenharmony_ci	gpu_write(gpu, REG_AXXX_CP_RB_CNTL,
2748c2ecf20Sopenharmony_ci		MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE);
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci	/* Set the ringbuffer address */
2778c2ecf20Sopenharmony_ci	gpu_write(gpu, REG_AXXX_CP_RB_BASE, lower_32_bits(gpu->rb[0]->iova));
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci	/* setup access protection: */
2808c2ecf20Sopenharmony_ci	gpu_write(gpu, REG_A3XX_CP_PROTECT_CTRL, 0x00000007);
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci	/* RBBM registers */
2838c2ecf20Sopenharmony_ci	gpu_write(gpu, REG_A3XX_CP_PROTECT(0), 0x63000040);
2848c2ecf20Sopenharmony_ci	gpu_write(gpu, REG_A3XX_CP_PROTECT(1), 0x62000080);
2858c2ecf20Sopenharmony_ci	gpu_write(gpu, REG_A3XX_CP_PROTECT(2), 0x600000cc);
2868c2ecf20Sopenharmony_ci	gpu_write(gpu, REG_A3XX_CP_PROTECT(3), 0x60000108);
2878c2ecf20Sopenharmony_ci	gpu_write(gpu, REG_A3XX_CP_PROTECT(4), 0x64000140);
2888c2ecf20Sopenharmony_ci	gpu_write(gpu, REG_A3XX_CP_PROTECT(5), 0x66000400);
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ci	/* CP registers */
2918c2ecf20Sopenharmony_ci	gpu_write(gpu, REG_A3XX_CP_PROTECT(6), 0x65000700);
2928c2ecf20Sopenharmony_ci	gpu_write(gpu, REG_A3XX_CP_PROTECT(7), 0x610007d8);
2938c2ecf20Sopenharmony_ci	gpu_write(gpu, REG_A3XX_CP_PROTECT(8), 0x620007e0);
2948c2ecf20Sopenharmony_ci	gpu_write(gpu, REG_A3XX_CP_PROTECT(9), 0x61001178);
2958c2ecf20Sopenharmony_ci	gpu_write(gpu, REG_A3XX_CP_PROTECT(10), 0x64001180);
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ci	/* RB registers */
2988c2ecf20Sopenharmony_ci	gpu_write(gpu, REG_A3XX_CP_PROTECT(11), 0x60003300);
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci	/* VBIF registers */
3018c2ecf20Sopenharmony_ci	gpu_write(gpu, REG_A3XX_CP_PROTECT(12), 0x6b00c000);
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci	/* NOTE: PM4/micro-engine firmware registers look to be the same
3048c2ecf20Sopenharmony_ci	 * for a2xx and a3xx.. we could possibly push that part down to
3058c2ecf20Sopenharmony_ci	 * adreno_gpu base class.  Or push both PM4 and PFP but
3068c2ecf20Sopenharmony_ci	 * parameterize the pfp ucode addr/data registers..
3078c2ecf20Sopenharmony_ci	 */
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_ci	/* Load PM4: */
3108c2ecf20Sopenharmony_ci	ptr = (uint32_t *)(adreno_gpu->fw[ADRENO_FW_PM4]->data);
3118c2ecf20Sopenharmony_ci	len = adreno_gpu->fw[ADRENO_FW_PM4]->size / 4;
3128c2ecf20Sopenharmony_ci	DBG("loading PM4 ucode version: %x", ptr[1]);
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ci	gpu_write(gpu, REG_AXXX_CP_DEBUG,
3158c2ecf20Sopenharmony_ci			AXXX_CP_DEBUG_DYNAMIC_CLK_DISABLE |
3168c2ecf20Sopenharmony_ci			AXXX_CP_DEBUG_MIU_128BIT_WRITE_ENABLE);
3178c2ecf20Sopenharmony_ci	gpu_write(gpu, REG_AXXX_CP_ME_RAM_WADDR, 0);
3188c2ecf20Sopenharmony_ci	for (i = 1; i < len; i++)
3198c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_AXXX_CP_ME_RAM_DATA, ptr[i]);
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci	/* Load PFP: */
3228c2ecf20Sopenharmony_ci	ptr = (uint32_t *)(adreno_gpu->fw[ADRENO_FW_PFP]->data);
3238c2ecf20Sopenharmony_ci	len = adreno_gpu->fw[ADRENO_FW_PFP]->size / 4;
3248c2ecf20Sopenharmony_ci	DBG("loading PFP ucode version: %x", ptr[5]);
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci	gpu_write(gpu, REG_A3XX_CP_PFP_UCODE_ADDR, 0);
3278c2ecf20Sopenharmony_ci	for (i = 1; i < len; i++)
3288c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_A3XX_CP_PFP_UCODE_DATA, ptr[i]);
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci	/* CP ROQ queue sizes (bytes) - RB:16, ST:16, IB1:32, IB2:64 */
3318c2ecf20Sopenharmony_ci	if (adreno_is_a305(adreno_gpu) || adreno_is_a306(adreno_gpu) ||
3328c2ecf20Sopenharmony_ci			adreno_is_a320(adreno_gpu)) {
3338c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_AXXX_CP_QUEUE_THRESHOLDS,
3348c2ecf20Sopenharmony_ci				AXXX_CP_QUEUE_THRESHOLDS_CSQ_IB1_START(2) |
3358c2ecf20Sopenharmony_ci				AXXX_CP_QUEUE_THRESHOLDS_CSQ_IB2_START(6) |
3368c2ecf20Sopenharmony_ci				AXXX_CP_QUEUE_THRESHOLDS_CSQ_ST_START(14));
3378c2ecf20Sopenharmony_ci	} else if (adreno_is_a330(adreno_gpu)) {
3388c2ecf20Sopenharmony_ci		/* NOTE: this (value take from downstream android driver)
3398c2ecf20Sopenharmony_ci		 * includes some bits outside of the known bitfields.  But
3408c2ecf20Sopenharmony_ci		 * A330 has this "MERCIU queue" thing too, which might
3418c2ecf20Sopenharmony_ci		 * explain a new bitfield or reshuffling:
3428c2ecf20Sopenharmony_ci		 */
3438c2ecf20Sopenharmony_ci		gpu_write(gpu, REG_AXXX_CP_QUEUE_THRESHOLDS, 0x003e2008);
3448c2ecf20Sopenharmony_ci	}
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ci	/* clear ME_HALT to start micro engine */
3478c2ecf20Sopenharmony_ci	gpu_write(gpu, REG_AXXX_CP_ME_CNTL, 0);
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci	return a3xx_me_init(gpu) ? 0 : -EINVAL;
3508c2ecf20Sopenharmony_ci}
3518c2ecf20Sopenharmony_ci
3528c2ecf20Sopenharmony_cistatic void a3xx_recover(struct msm_gpu *gpu)
3538c2ecf20Sopenharmony_ci{
3548c2ecf20Sopenharmony_ci	int i;
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_ci	adreno_dump_info(gpu);
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_ci	for (i = 0; i < 8; i++) {
3598c2ecf20Sopenharmony_ci		printk("CP_SCRATCH_REG%d: %u\n", i,
3608c2ecf20Sopenharmony_ci			gpu_read(gpu, REG_AXXX_CP_SCRATCH_REG0 + i));
3618c2ecf20Sopenharmony_ci	}
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_ci	/* dump registers before resetting gpu, if enabled: */
3648c2ecf20Sopenharmony_ci	if (hang_debug)
3658c2ecf20Sopenharmony_ci		a3xx_dump(gpu);
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ci	gpu_write(gpu, REG_A3XX_RBBM_SW_RESET_CMD, 1);
3688c2ecf20Sopenharmony_ci	gpu_read(gpu, REG_A3XX_RBBM_SW_RESET_CMD);
3698c2ecf20Sopenharmony_ci	gpu_write(gpu, REG_A3XX_RBBM_SW_RESET_CMD, 0);
3708c2ecf20Sopenharmony_ci	adreno_recover(gpu);
3718c2ecf20Sopenharmony_ci}
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_cistatic void a3xx_destroy(struct msm_gpu *gpu)
3748c2ecf20Sopenharmony_ci{
3758c2ecf20Sopenharmony_ci	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
3768c2ecf20Sopenharmony_ci	struct a3xx_gpu *a3xx_gpu = to_a3xx_gpu(adreno_gpu);
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_ci	DBG("%s", gpu->name);
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ci	adreno_gpu_cleanup(adreno_gpu);
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_ci	adreno_gpu_ocmem_cleanup(&a3xx_gpu->ocmem);
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ci	kfree(a3xx_gpu);
3858c2ecf20Sopenharmony_ci}
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_cistatic bool a3xx_idle(struct msm_gpu *gpu)
3888c2ecf20Sopenharmony_ci{
3898c2ecf20Sopenharmony_ci	/* wait for ringbuffer to drain: */
3908c2ecf20Sopenharmony_ci	if (!adreno_idle(gpu, gpu->rb[0]))
3918c2ecf20Sopenharmony_ci		return false;
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_ci	/* then wait for GPU to finish: */
3948c2ecf20Sopenharmony_ci	if (spin_until(!(gpu_read(gpu, REG_A3XX_RBBM_STATUS) &
3958c2ecf20Sopenharmony_ci			A3XX_RBBM_STATUS_GPU_BUSY))) {
3968c2ecf20Sopenharmony_ci		DRM_ERROR("%s: timeout waiting for GPU to idle!\n", gpu->name);
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ci		/* TODO maybe we need to reset GPU here to recover from hang? */
3998c2ecf20Sopenharmony_ci		return false;
4008c2ecf20Sopenharmony_ci	}
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci	return true;
4038c2ecf20Sopenharmony_ci}
4048c2ecf20Sopenharmony_ci
4058c2ecf20Sopenharmony_cistatic irqreturn_t a3xx_irq(struct msm_gpu *gpu)
4068c2ecf20Sopenharmony_ci{
4078c2ecf20Sopenharmony_ci	uint32_t status;
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ci	status = gpu_read(gpu, REG_A3XX_RBBM_INT_0_STATUS);
4108c2ecf20Sopenharmony_ci	DBG("%s: %08x", gpu->name, status);
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_ci	// TODO
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_ci	gpu_write(gpu, REG_A3XX_RBBM_INT_CLEAR_CMD, status);
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci	msm_gpu_retire(gpu);
4178c2ecf20Sopenharmony_ci
4188c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
4198c2ecf20Sopenharmony_ci}
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_cistatic const unsigned int a3xx_registers[] = {
4228c2ecf20Sopenharmony_ci	0x0000, 0x0002, 0x0010, 0x0012, 0x0018, 0x0018, 0x0020, 0x0027,
4238c2ecf20Sopenharmony_ci	0x0029, 0x002b, 0x002e, 0x0033, 0x0040, 0x0042, 0x0050, 0x005c,
4248c2ecf20Sopenharmony_ci	0x0060, 0x006c, 0x0080, 0x0082, 0x0084, 0x0088, 0x0090, 0x00e5,
4258c2ecf20Sopenharmony_ci	0x00ea, 0x00ed, 0x0100, 0x0100, 0x0110, 0x0123, 0x01c0, 0x01c1,
4268c2ecf20Sopenharmony_ci	0x01c3, 0x01c5, 0x01c7, 0x01c7, 0x01d5, 0x01d9, 0x01dc, 0x01dd,
4278c2ecf20Sopenharmony_ci	0x01ea, 0x01ea, 0x01ee, 0x01f1, 0x01f5, 0x01f5, 0x01fc, 0x01ff,
4288c2ecf20Sopenharmony_ci	0x0440, 0x0440, 0x0443, 0x0443, 0x0445, 0x0445, 0x044d, 0x044f,
4298c2ecf20Sopenharmony_ci	0x0452, 0x0452, 0x0454, 0x046f, 0x047c, 0x047c, 0x047f, 0x047f,
4308c2ecf20Sopenharmony_ci	0x0578, 0x057f, 0x0600, 0x0602, 0x0605, 0x0607, 0x060a, 0x060e,
4318c2ecf20Sopenharmony_ci	0x0612, 0x0614, 0x0c01, 0x0c02, 0x0c06, 0x0c1d, 0x0c3d, 0x0c3f,
4328c2ecf20Sopenharmony_ci	0x0c48, 0x0c4b, 0x0c80, 0x0c80, 0x0c88, 0x0c8b, 0x0ca0, 0x0cb7,
4338c2ecf20Sopenharmony_ci	0x0cc0, 0x0cc1, 0x0cc6, 0x0cc7, 0x0ce4, 0x0ce5, 0x0e00, 0x0e05,
4348c2ecf20Sopenharmony_ci	0x0e0c, 0x0e0c, 0x0e22, 0x0e23, 0x0e41, 0x0e45, 0x0e64, 0x0e65,
4358c2ecf20Sopenharmony_ci	0x0e80, 0x0e82, 0x0e84, 0x0e89, 0x0ea0, 0x0ea1, 0x0ea4, 0x0ea7,
4368c2ecf20Sopenharmony_ci	0x0ec4, 0x0ecb, 0x0ee0, 0x0ee0, 0x0f00, 0x0f01, 0x0f03, 0x0f09,
4378c2ecf20Sopenharmony_ci	0x2040, 0x2040, 0x2044, 0x2044, 0x2048, 0x204d, 0x2068, 0x2069,
4388c2ecf20Sopenharmony_ci	0x206c, 0x206d, 0x2070, 0x2070, 0x2072, 0x2072, 0x2074, 0x2075,
4398c2ecf20Sopenharmony_ci	0x2079, 0x207a, 0x20c0, 0x20d3, 0x20e4, 0x20ef, 0x2100, 0x2109,
4408c2ecf20Sopenharmony_ci	0x210c, 0x210c, 0x210e, 0x210e, 0x2110, 0x2111, 0x2114, 0x2115,
4418c2ecf20Sopenharmony_ci	0x21e4, 0x21e4, 0x21ea, 0x21ea, 0x21ec, 0x21ed, 0x21f0, 0x21f0,
4428c2ecf20Sopenharmony_ci	0x2200, 0x2212, 0x2214, 0x2217, 0x221a, 0x221a, 0x2240, 0x227e,
4438c2ecf20Sopenharmony_ci	0x2280, 0x228b, 0x22c0, 0x22c0, 0x22c4, 0x22ce, 0x22d0, 0x22d8,
4448c2ecf20Sopenharmony_ci	0x22df, 0x22e6, 0x22e8, 0x22e9, 0x22ec, 0x22ec, 0x22f0, 0x22f7,
4458c2ecf20Sopenharmony_ci	0x22ff, 0x22ff, 0x2340, 0x2343, 0x2440, 0x2440, 0x2444, 0x2444,
4468c2ecf20Sopenharmony_ci	0x2448, 0x244d, 0x2468, 0x2469, 0x246c, 0x246d, 0x2470, 0x2470,
4478c2ecf20Sopenharmony_ci	0x2472, 0x2472, 0x2474, 0x2475, 0x2479, 0x247a, 0x24c0, 0x24d3,
4488c2ecf20Sopenharmony_ci	0x24e4, 0x24ef, 0x2500, 0x2509, 0x250c, 0x250c, 0x250e, 0x250e,
4498c2ecf20Sopenharmony_ci	0x2510, 0x2511, 0x2514, 0x2515, 0x25e4, 0x25e4, 0x25ea, 0x25ea,
4508c2ecf20Sopenharmony_ci	0x25ec, 0x25ed, 0x25f0, 0x25f0, 0x2600, 0x2612, 0x2614, 0x2617,
4518c2ecf20Sopenharmony_ci	0x261a, 0x261a, 0x2640, 0x267e, 0x2680, 0x268b, 0x26c0, 0x26c0,
4528c2ecf20Sopenharmony_ci	0x26c4, 0x26ce, 0x26d0, 0x26d8, 0x26df, 0x26e6, 0x26e8, 0x26e9,
4538c2ecf20Sopenharmony_ci	0x26ec, 0x26ec, 0x26f0, 0x26f7, 0x26ff, 0x26ff, 0x2740, 0x2743,
4548c2ecf20Sopenharmony_ci	0x300c, 0x300e, 0x301c, 0x301d, 0x302a, 0x302a, 0x302c, 0x302d,
4558c2ecf20Sopenharmony_ci	0x3030, 0x3031, 0x3034, 0x3036, 0x303c, 0x303c, 0x305e, 0x305f,
4568c2ecf20Sopenharmony_ci	~0   /* sentinel */
4578c2ecf20Sopenharmony_ci};
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_ci/* would be nice to not have to duplicate the _show() stuff with printk(): */
4608c2ecf20Sopenharmony_cistatic void a3xx_dump(struct msm_gpu *gpu)
4618c2ecf20Sopenharmony_ci{
4628c2ecf20Sopenharmony_ci	printk("status:   %08x\n",
4638c2ecf20Sopenharmony_ci			gpu_read(gpu, REG_A3XX_RBBM_STATUS));
4648c2ecf20Sopenharmony_ci	adreno_dump(gpu);
4658c2ecf20Sopenharmony_ci}
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_cistatic struct msm_gpu_state *a3xx_gpu_state_get(struct msm_gpu *gpu)
4688c2ecf20Sopenharmony_ci{
4698c2ecf20Sopenharmony_ci	struct msm_gpu_state *state = kzalloc(sizeof(*state), GFP_KERNEL);
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_ci	if (!state)
4728c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
4738c2ecf20Sopenharmony_ci
4748c2ecf20Sopenharmony_ci	adreno_gpu_state_get(gpu, state);
4758c2ecf20Sopenharmony_ci
4768c2ecf20Sopenharmony_ci	state->rbbm_status = gpu_read(gpu, REG_A3XX_RBBM_STATUS);
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_ci	return state;
4798c2ecf20Sopenharmony_ci}
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_cistatic u32 a3xx_get_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
4828c2ecf20Sopenharmony_ci{
4838c2ecf20Sopenharmony_ci	ring->memptrs->rptr = gpu_read(gpu, REG_AXXX_CP_RB_RPTR);
4848c2ecf20Sopenharmony_ci	return ring->memptrs->rptr;
4858c2ecf20Sopenharmony_ci}
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_cistatic const struct adreno_gpu_funcs funcs = {
4888c2ecf20Sopenharmony_ci	.base = {
4898c2ecf20Sopenharmony_ci		.get_param = adreno_get_param,
4908c2ecf20Sopenharmony_ci		.hw_init = a3xx_hw_init,
4918c2ecf20Sopenharmony_ci		.pm_suspend = msm_gpu_pm_suspend,
4928c2ecf20Sopenharmony_ci		.pm_resume = msm_gpu_pm_resume,
4938c2ecf20Sopenharmony_ci		.recover = a3xx_recover,
4948c2ecf20Sopenharmony_ci		.submit = a3xx_submit,
4958c2ecf20Sopenharmony_ci		.active_ring = adreno_active_ring,
4968c2ecf20Sopenharmony_ci		.irq = a3xx_irq,
4978c2ecf20Sopenharmony_ci		.destroy = a3xx_destroy,
4988c2ecf20Sopenharmony_ci#if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP)
4998c2ecf20Sopenharmony_ci		.show = adreno_show,
5008c2ecf20Sopenharmony_ci#endif
5018c2ecf20Sopenharmony_ci		.gpu_state_get = a3xx_gpu_state_get,
5028c2ecf20Sopenharmony_ci		.gpu_state_put = adreno_gpu_state_put,
5038c2ecf20Sopenharmony_ci		.create_address_space = adreno_iommu_create_address_space,
5048c2ecf20Sopenharmony_ci		.get_rptr = a3xx_get_rptr,
5058c2ecf20Sopenharmony_ci	},
5068c2ecf20Sopenharmony_ci};
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_cistatic const struct msm_gpu_perfcntr perfcntrs[] = {
5098c2ecf20Sopenharmony_ci	{ REG_A3XX_SP_PERFCOUNTER6_SELECT, REG_A3XX_RBBM_PERFCTR_SP_6_LO,
5108c2ecf20Sopenharmony_ci			SP_ALU_ACTIVE_CYCLES, "ALUACTIVE" },
5118c2ecf20Sopenharmony_ci	{ REG_A3XX_SP_PERFCOUNTER7_SELECT, REG_A3XX_RBBM_PERFCTR_SP_7_LO,
5128c2ecf20Sopenharmony_ci			SP_FS_FULL_ALU_INSTRUCTIONS, "ALUFULL" },
5138c2ecf20Sopenharmony_ci};
5148c2ecf20Sopenharmony_ci
5158c2ecf20Sopenharmony_cistruct msm_gpu *a3xx_gpu_init(struct drm_device *dev)
5168c2ecf20Sopenharmony_ci{
5178c2ecf20Sopenharmony_ci	struct a3xx_gpu *a3xx_gpu = NULL;
5188c2ecf20Sopenharmony_ci	struct adreno_gpu *adreno_gpu;
5198c2ecf20Sopenharmony_ci	struct msm_gpu *gpu;
5208c2ecf20Sopenharmony_ci	struct msm_drm_private *priv = dev->dev_private;
5218c2ecf20Sopenharmony_ci	struct platform_device *pdev = priv->gpu_pdev;
5228c2ecf20Sopenharmony_ci	int ret;
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci	if (!pdev) {
5258c2ecf20Sopenharmony_ci		DRM_DEV_ERROR(dev->dev, "no a3xx device\n");
5268c2ecf20Sopenharmony_ci		ret = -ENXIO;
5278c2ecf20Sopenharmony_ci		goto fail;
5288c2ecf20Sopenharmony_ci	}
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_ci	a3xx_gpu = kzalloc(sizeof(*a3xx_gpu), GFP_KERNEL);
5318c2ecf20Sopenharmony_ci	if (!a3xx_gpu) {
5328c2ecf20Sopenharmony_ci		ret = -ENOMEM;
5338c2ecf20Sopenharmony_ci		goto fail;
5348c2ecf20Sopenharmony_ci	}
5358c2ecf20Sopenharmony_ci
5368c2ecf20Sopenharmony_ci	adreno_gpu = &a3xx_gpu->base;
5378c2ecf20Sopenharmony_ci	gpu = &adreno_gpu->base;
5388c2ecf20Sopenharmony_ci
5398c2ecf20Sopenharmony_ci	gpu->perfcntrs = perfcntrs;
5408c2ecf20Sopenharmony_ci	gpu->num_perfcntrs = ARRAY_SIZE(perfcntrs);
5418c2ecf20Sopenharmony_ci
5428c2ecf20Sopenharmony_ci	adreno_gpu->registers = a3xx_registers;
5438c2ecf20Sopenharmony_ci
5448c2ecf20Sopenharmony_ci	ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1);
5458c2ecf20Sopenharmony_ci	if (ret)
5468c2ecf20Sopenharmony_ci		goto fail;
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_ci	/* if needed, allocate gmem: */
5498c2ecf20Sopenharmony_ci	if (adreno_is_a330(adreno_gpu)) {
5508c2ecf20Sopenharmony_ci		ret = adreno_gpu_ocmem_init(&adreno_gpu->base.pdev->dev,
5518c2ecf20Sopenharmony_ci					    adreno_gpu, &a3xx_gpu->ocmem);
5528c2ecf20Sopenharmony_ci		if (ret)
5538c2ecf20Sopenharmony_ci			goto fail;
5548c2ecf20Sopenharmony_ci	}
5558c2ecf20Sopenharmony_ci
5568c2ecf20Sopenharmony_ci	if (!gpu->aspace) {
5578c2ecf20Sopenharmony_ci		/* TODO we think it is possible to configure the GPU to
5588c2ecf20Sopenharmony_ci		 * restrict access to VRAM carveout.  But the required
5598c2ecf20Sopenharmony_ci		 * registers are unknown.  For now just bail out and
5608c2ecf20Sopenharmony_ci		 * limp along with just modesetting.  If it turns out
5618c2ecf20Sopenharmony_ci		 * to not be possible to restrict access, then we must
5628c2ecf20Sopenharmony_ci		 * implement a cmdstream validator.
5638c2ecf20Sopenharmony_ci		 */
5648c2ecf20Sopenharmony_ci		DRM_DEV_ERROR(dev->dev, "No memory protection without IOMMU\n");
5658c2ecf20Sopenharmony_ci		ret = -ENXIO;
5668c2ecf20Sopenharmony_ci		goto fail;
5678c2ecf20Sopenharmony_ci	}
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ci	/*
5708c2ecf20Sopenharmony_ci	 * Set the ICC path to maximum speed for now by multiplying the fastest
5718c2ecf20Sopenharmony_ci	 * frequency by the bus width (8). We'll want to scale this later on to
5728c2ecf20Sopenharmony_ci	 * improve battery life.
5738c2ecf20Sopenharmony_ci	 */
5748c2ecf20Sopenharmony_ci	icc_set_bw(gpu->icc_path, 0, Bps_to_icc(gpu->fast_rate) * 8);
5758c2ecf20Sopenharmony_ci	icc_set_bw(gpu->ocmem_icc_path, 0, Bps_to_icc(gpu->fast_rate) * 8);
5768c2ecf20Sopenharmony_ci
5778c2ecf20Sopenharmony_ci	return gpu;
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_cifail:
5808c2ecf20Sopenharmony_ci	if (a3xx_gpu)
5818c2ecf20Sopenharmony_ci		a3xx_destroy(&a3xx_gpu->base.base);
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_ci	return ERR_PTR(ret);
5848c2ecf20Sopenharmony_ci}
585