xref: /openbmc/linux/drivers/gpu/drm/msm/adreno/a2xx_gpu.c (revision db07ce5d)
121af872cSJonathan Marek // SPDX-License-Identifier: GPL-2.0
221af872cSJonathan Marek /* Copyright (c) 2018 The Linux Foundation. All rights reserved. */
321af872cSJonathan Marek 
421af872cSJonathan Marek #include "a2xx_gpu.h"
5c2052a4eSJonathan Marek #include "msm_gem.h"
6c2052a4eSJonathan Marek #include "msm_mmu.h"
721af872cSJonathan Marek 
821af872cSJonathan Marek extern bool hang_debug;
921af872cSJonathan Marek 
1021af872cSJonathan Marek static void a2xx_dump(struct msm_gpu *gpu);
1121af872cSJonathan Marek static bool a2xx_idle(struct msm_gpu *gpu);
1221af872cSJonathan Marek 
a2xx_submit(struct msm_gpu * gpu,struct msm_gem_submit * submit)132fb7487aSJordan Crouse static void a2xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
142fb7487aSJordan Crouse {
152fb7487aSJordan Crouse 	struct msm_ringbuffer *ring = submit->ring;
162fb7487aSJordan Crouse 	unsigned int i;
172fb7487aSJordan Crouse 
182fb7487aSJordan Crouse 	for (i = 0; i < submit->nr_cmds; i++) {
192fb7487aSJordan Crouse 		switch (submit->cmd[i].type) {
202fb7487aSJordan Crouse 		case MSM_SUBMIT_CMD_IB_TARGET_BUF:
212fb7487aSJordan Crouse 			/* ignore IB-targets */
222fb7487aSJordan Crouse 			break;
232fb7487aSJordan Crouse 		case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
242fb7487aSJordan Crouse 			/* ignore if there has not been a ctx switch: */
251d054c9bSRob Clark 			if (gpu->cur_ctx_seqno == submit->queue->ctx->seqno)
262fb7487aSJordan Crouse 				break;
272fb7487aSJordan Crouse 			fallthrough;
282fb7487aSJordan Crouse 		case MSM_SUBMIT_CMD_BUF:
292fb7487aSJordan Crouse 			OUT_PKT3(ring, CP_INDIRECT_BUFFER_PFD, 2);
302fb7487aSJordan Crouse 			OUT_RING(ring, lower_32_bits(submit->cmd[i].iova));
312fb7487aSJordan Crouse 			OUT_RING(ring, submit->cmd[i].size);
322fb7487aSJordan Crouse 			OUT_PKT2(ring);
332fb7487aSJordan Crouse 			break;
342fb7487aSJordan Crouse 		}
352fb7487aSJordan Crouse 	}
362fb7487aSJordan Crouse 
372fb7487aSJordan Crouse 	OUT_PKT0(ring, REG_AXXX_CP_SCRATCH_REG2, 1);
382fb7487aSJordan Crouse 	OUT_RING(ring, submit->seqno);
392fb7487aSJordan Crouse 
402fb7487aSJordan Crouse 	/* wait for idle before cache flush/interrupt */
412fb7487aSJordan Crouse 	OUT_PKT3(ring, CP_WAIT_FOR_IDLE, 1);
422fb7487aSJordan Crouse 	OUT_RING(ring, 0x00000000);
432fb7487aSJordan Crouse 
442fb7487aSJordan Crouse 	OUT_PKT3(ring, CP_EVENT_WRITE, 3);
452fb7487aSJordan Crouse 	OUT_RING(ring, CACHE_FLUSH_TS);
462fb7487aSJordan Crouse 	OUT_RING(ring, rbmemptr(ring, fence));
472fb7487aSJordan Crouse 	OUT_RING(ring, submit->seqno);
482fb7487aSJordan Crouse 	OUT_PKT3(ring, CP_INTERRUPT, 1);
492fb7487aSJordan Crouse 	OUT_RING(ring, 0x80000000);
502fb7487aSJordan Crouse 
512fb7487aSJordan Crouse 	adreno_flush(gpu, ring, REG_AXXX_CP_RB_WPTR);
522fb7487aSJordan Crouse }
532fb7487aSJordan Crouse 
a2xx_me_init(struct msm_gpu * gpu)5421af872cSJonathan Marek static bool a2xx_me_init(struct msm_gpu *gpu)
5521af872cSJonathan Marek {
5630229507SDmitry Baryshkov 	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
5730229507SDmitry Baryshkov 	struct a2xx_gpu *a2xx_gpu = to_a2xx_gpu(adreno_gpu);
5821af872cSJonathan Marek 	struct msm_ringbuffer *ring = gpu->rb[0];
5921af872cSJonathan Marek 
6021af872cSJonathan Marek 	OUT_PKT3(ring, CP_ME_INIT, 18);
6121af872cSJonathan Marek 
6221af872cSJonathan Marek 	/* All fields present (bits 9:0) */
6321af872cSJonathan Marek 	OUT_RING(ring, 0x000003ff);
6421af872cSJonathan Marek 	/* Disable/Enable Real-Time Stream processing (present but ignored) */
6521af872cSJonathan Marek 	OUT_RING(ring, 0x00000000);
6621af872cSJonathan Marek 	/* Enable (2D <-> 3D) implicit synchronization (present but ignored) */
6721af872cSJonathan Marek 	OUT_RING(ring, 0x00000000);
6821af872cSJonathan Marek 
6921af872cSJonathan Marek 	OUT_RING(ring, REG_A2XX_RB_SURFACE_INFO - 0x2000);
7021af872cSJonathan Marek 	OUT_RING(ring, REG_A2XX_PA_SC_WINDOW_OFFSET - 0x2000);
7121af872cSJonathan Marek 	OUT_RING(ring, REG_A2XX_VGT_MAX_VTX_INDX - 0x2000);
7221af872cSJonathan Marek 	OUT_RING(ring, REG_A2XX_SQ_PROGRAM_CNTL - 0x2000);
7321af872cSJonathan Marek 	OUT_RING(ring, REG_A2XX_RB_DEPTHCONTROL - 0x2000);
7421af872cSJonathan Marek 	OUT_RING(ring, REG_A2XX_PA_SU_POINT_SIZE - 0x2000);
7521af872cSJonathan Marek 	OUT_RING(ring, REG_A2XX_PA_SC_LINE_CNTL - 0x2000);
7621af872cSJonathan Marek 	OUT_RING(ring, REG_A2XX_PA_SU_POLY_OFFSET_FRONT_SCALE - 0x2000);
7721af872cSJonathan Marek 
7821af872cSJonathan Marek 	/* Vertex and Pixel Shader Start Addresses in instructions
7921af872cSJonathan Marek 	 * (3 DWORDS per instruction) */
8021af872cSJonathan Marek 	OUT_RING(ring, 0x80000180);
8121af872cSJonathan Marek 	/* Maximum Contexts */
8221af872cSJonathan Marek 	OUT_RING(ring, 0x00000001);
8321af872cSJonathan Marek 	/* Write Confirm Interval and The CP will wait the
8421af872cSJonathan Marek 	 * wait_interval * 16 clocks between polling  */
8521af872cSJonathan Marek 	OUT_RING(ring, 0x00000000);
8621af872cSJonathan Marek 	/* NQ and External Memory Swap */
8721af872cSJonathan Marek 	OUT_RING(ring, 0x00000000);
8821af872cSJonathan Marek 	/* protected mode error checking (0x1f2 is REG_AXXX_CP_INT_CNTL) */
8930229507SDmitry Baryshkov 	if (a2xx_gpu->protection_disabled)
9030229507SDmitry Baryshkov 		OUT_RING(ring, 0x00000000);
9130229507SDmitry Baryshkov 	else
9221af872cSJonathan Marek 		OUT_RING(ring, 0x200001f2);
9321af872cSJonathan Marek 	/* Disable header dumping and Header dump address */
9421af872cSJonathan Marek 	OUT_RING(ring, 0x00000000);
9521af872cSJonathan Marek 	/* Header dump size */
9621af872cSJonathan Marek 	OUT_RING(ring, 0x00000000);
9721af872cSJonathan Marek 
9830229507SDmitry Baryshkov 	if (!a2xx_gpu->protection_disabled) {
9921af872cSJonathan Marek 		/* enable protected mode */
10021af872cSJonathan Marek 		OUT_PKT3(ring, CP_SET_PROTECTED_MODE, 1);
10121af872cSJonathan Marek 		OUT_RING(ring, 1);
10230229507SDmitry Baryshkov 	}
10321af872cSJonathan Marek 
1042fb7487aSJordan Crouse 	adreno_flush(gpu, ring, REG_AXXX_CP_RB_WPTR);
10521af872cSJonathan Marek 	return a2xx_idle(gpu);
10621af872cSJonathan Marek }
10721af872cSJonathan Marek 
a2xx_hw_init(struct msm_gpu * gpu)10821af872cSJonathan Marek static int a2xx_hw_init(struct msm_gpu *gpu)
10921af872cSJonathan Marek {
11021af872cSJonathan Marek 	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
11130229507SDmitry Baryshkov 	struct a2xx_gpu *a2xx_gpu = to_a2xx_gpu(adreno_gpu);
112c2052a4eSJonathan Marek 	dma_addr_t pt_base, tran_error;
11321af872cSJonathan Marek 	uint32_t *ptr, len;
11421af872cSJonathan Marek 	int i, ret;
11521af872cSJonathan Marek 
116c2052a4eSJonathan Marek 	msm_gpummu_params(gpu->aspace->mmu, &pt_base, &tran_error);
117c2052a4eSJonathan Marek 
11821af872cSJonathan Marek 	DBG("%s", gpu->name);
11921af872cSJonathan Marek 
12021af872cSJonathan Marek 	/* halt ME to avoid ucode upload issues on a20x */
12121af872cSJonathan Marek 	gpu_write(gpu, REG_AXXX_CP_ME_CNTL, AXXX_CP_ME_CNTL_HALT);
12221af872cSJonathan Marek 
12321af872cSJonathan Marek 	gpu_write(gpu, REG_A2XX_RBBM_PM_OVERRIDE1, 0xfffffffe);
12421af872cSJonathan Marek 	gpu_write(gpu, REG_A2XX_RBBM_PM_OVERRIDE2, 0xffffffff);
12521af872cSJonathan Marek 
12621af872cSJonathan Marek 	/* note: kgsl uses 0x00000001 after first reset on a22x */
12721af872cSJonathan Marek 	gpu_write(gpu, REG_A2XX_RBBM_SOFT_RESET, 0xffffffff);
12821af872cSJonathan Marek 	msleep(30);
12921af872cSJonathan Marek 	gpu_write(gpu, REG_A2XX_RBBM_SOFT_RESET, 0x00000000);
13021af872cSJonathan Marek 
13121af872cSJonathan Marek 	if (adreno_is_a225(adreno_gpu))
13221af872cSJonathan Marek 		gpu_write(gpu, REG_A2XX_SQ_FLOW_CONTROL, 0x18000000);
13321af872cSJonathan Marek 
13421af872cSJonathan Marek 	/* note: kgsl uses 0x0000ffff for a20x */
13521af872cSJonathan Marek 	gpu_write(gpu, REG_A2XX_RBBM_CNTL, 0x00004442);
13621af872cSJonathan Marek 
137c2052a4eSJonathan Marek 	/* MPU: physical range */
138c2052a4eSJonathan Marek 	gpu_write(gpu, REG_A2XX_MH_MMU_MPU_BASE, 0x00000000);
13921af872cSJonathan Marek 	gpu_write(gpu, REG_A2XX_MH_MMU_MPU_END, 0xfffff000);
140c2052a4eSJonathan Marek 
141c2052a4eSJonathan Marek 	gpu_write(gpu, REG_A2XX_MH_MMU_CONFIG, A2XX_MH_MMU_CONFIG_MMU_ENABLE |
142c2052a4eSJonathan Marek 		A2XX_MH_MMU_CONFIG_RB_W_CLNT_BEHAVIOR(BEH_TRAN_RNG) |
143c2052a4eSJonathan Marek 		A2XX_MH_MMU_CONFIG_CP_W_CLNT_BEHAVIOR(BEH_TRAN_RNG) |
144c2052a4eSJonathan Marek 		A2XX_MH_MMU_CONFIG_CP_R0_CLNT_BEHAVIOR(BEH_TRAN_RNG) |
145c2052a4eSJonathan Marek 		A2XX_MH_MMU_CONFIG_CP_R1_CLNT_BEHAVIOR(BEH_TRAN_RNG) |
146c2052a4eSJonathan Marek 		A2XX_MH_MMU_CONFIG_CP_R2_CLNT_BEHAVIOR(BEH_TRAN_RNG) |
147c2052a4eSJonathan Marek 		A2XX_MH_MMU_CONFIG_CP_R3_CLNT_BEHAVIOR(BEH_TRAN_RNG) |
148c2052a4eSJonathan Marek 		A2XX_MH_MMU_CONFIG_CP_R4_CLNT_BEHAVIOR(BEH_TRAN_RNG) |
149c2052a4eSJonathan Marek 		A2XX_MH_MMU_CONFIG_VGT_R0_CLNT_BEHAVIOR(BEH_TRAN_RNG) |
150c2052a4eSJonathan Marek 		A2XX_MH_MMU_CONFIG_VGT_R1_CLNT_BEHAVIOR(BEH_TRAN_RNG) |
151c2052a4eSJonathan Marek 		A2XX_MH_MMU_CONFIG_TC_R_CLNT_BEHAVIOR(BEH_TRAN_RNG) |
152c2052a4eSJonathan Marek 		A2XX_MH_MMU_CONFIG_PA_W_CLNT_BEHAVIOR(BEH_TRAN_RNG));
153c2052a4eSJonathan Marek 
154c2052a4eSJonathan Marek 	/* same as parameters in adreno_gpu */
155c2052a4eSJonathan Marek 	gpu_write(gpu, REG_A2XX_MH_MMU_VA_RANGE, SZ_16M |
156c2052a4eSJonathan Marek 		A2XX_MH_MMU_VA_RANGE_NUM_64KB_REGIONS(0xfff));
157c2052a4eSJonathan Marek 
158c2052a4eSJonathan Marek 	gpu_write(gpu, REG_A2XX_MH_MMU_PT_BASE, pt_base);
159c2052a4eSJonathan Marek 	gpu_write(gpu, REG_A2XX_MH_MMU_TRAN_ERROR, tran_error);
160c2052a4eSJonathan Marek 
161c2052a4eSJonathan Marek 	gpu_write(gpu, REG_A2XX_MH_MMU_INVALIDATE,
162c2052a4eSJonathan Marek 		A2XX_MH_MMU_INVALIDATE_INVALIDATE_ALL |
163c2052a4eSJonathan Marek 		A2XX_MH_MMU_INVALIDATE_INVALIDATE_TC);
164c2052a4eSJonathan Marek 
16521af872cSJonathan Marek 	gpu_write(gpu, REG_A2XX_MH_ARBITER_CONFIG,
16621af872cSJonathan Marek 		A2XX_MH_ARBITER_CONFIG_SAME_PAGE_LIMIT(16) |
16721af872cSJonathan Marek 		A2XX_MH_ARBITER_CONFIG_L1_ARB_ENABLE |
16821af872cSJonathan Marek 		A2XX_MH_ARBITER_CONFIG_L1_ARB_HOLD_ENABLE |
16921af872cSJonathan Marek 		A2XX_MH_ARBITER_CONFIG_PAGE_SIZE(1) |
17021af872cSJonathan Marek 		A2XX_MH_ARBITER_CONFIG_TC_REORDER_ENABLE |
17121af872cSJonathan Marek 		A2XX_MH_ARBITER_CONFIG_TC_ARB_HOLD_ENABLE |
17221af872cSJonathan Marek 		A2XX_MH_ARBITER_CONFIG_IN_FLIGHT_LIMIT_ENABLE |
17321af872cSJonathan Marek 		A2XX_MH_ARBITER_CONFIG_IN_FLIGHT_LIMIT(8) |
17421af872cSJonathan Marek 		A2XX_MH_ARBITER_CONFIG_CP_CLNT_ENABLE |
17521af872cSJonathan Marek 		A2XX_MH_ARBITER_CONFIG_VGT_CLNT_ENABLE |
17621af872cSJonathan Marek 		A2XX_MH_ARBITER_CONFIG_TC_CLNT_ENABLE |
17721af872cSJonathan Marek 		A2XX_MH_ARBITER_CONFIG_RB_CLNT_ENABLE |
17821af872cSJonathan Marek 		A2XX_MH_ARBITER_CONFIG_PA_CLNT_ENABLE);
17921af872cSJonathan Marek 	if (!adreno_is_a20x(adreno_gpu))
18021af872cSJonathan Marek 		gpu_write(gpu, REG_A2XX_MH_CLNT_INTF_CTRL_CONFIG1, 0x00032f07);
18121af872cSJonathan Marek 
18221af872cSJonathan Marek 	gpu_write(gpu, REG_A2XX_SQ_VS_PROGRAM, 0x00000000);
18321af872cSJonathan Marek 	gpu_write(gpu, REG_A2XX_SQ_PS_PROGRAM, 0x00000000);
18421af872cSJonathan Marek 
18521af872cSJonathan Marek 	gpu_write(gpu, REG_A2XX_RBBM_PM_OVERRIDE1, 0); /* 0x200 for msm8960? */
18621af872cSJonathan Marek 	gpu_write(gpu, REG_A2XX_RBBM_PM_OVERRIDE2, 0); /* 0x80/0x1a0 for a22x? */
18721af872cSJonathan Marek 
18821af872cSJonathan Marek 	/* note: gsl doesn't set this */
18921af872cSJonathan Marek 	gpu_write(gpu, REG_A2XX_RBBM_DEBUG, 0x00080000);
19021af872cSJonathan Marek 
191c2052a4eSJonathan Marek 	gpu_write(gpu, REG_A2XX_RBBM_INT_CNTL,
192c2052a4eSJonathan Marek 		A2XX_RBBM_INT_CNTL_RDERR_INT_MASK);
193c2052a4eSJonathan Marek 	gpu_write(gpu, REG_AXXX_CP_INT_CNTL,
194c2052a4eSJonathan Marek 		AXXX_CP_INT_CNTL_T0_PACKET_IN_IB_MASK |
195c2052a4eSJonathan Marek 		AXXX_CP_INT_CNTL_OPCODE_ERROR_MASK |
196c2052a4eSJonathan Marek 		AXXX_CP_INT_CNTL_PROTECTED_MODE_ERROR_MASK |
197c2052a4eSJonathan Marek 		AXXX_CP_INT_CNTL_RESERVED_BIT_ERROR_MASK |
198c2052a4eSJonathan Marek 		AXXX_CP_INT_CNTL_IB_ERROR_MASK |
199c2052a4eSJonathan Marek 		AXXX_CP_INT_CNTL_IB1_INT_MASK |
200c2052a4eSJonathan Marek 		AXXX_CP_INT_CNTL_RB_INT_MASK);
20121af872cSJonathan Marek 	gpu_write(gpu, REG_A2XX_SQ_INT_CNTL, 0);
202c2052a4eSJonathan Marek 	gpu_write(gpu, REG_A2XX_MH_INTERRUPT_MASK,
203c2052a4eSJonathan Marek 		A2XX_MH_INTERRUPT_MASK_AXI_READ_ERROR |
204c2052a4eSJonathan Marek 		A2XX_MH_INTERRUPT_MASK_AXI_WRITE_ERROR |
205c2052a4eSJonathan Marek 		A2XX_MH_INTERRUPT_MASK_MMU_PAGE_FAULT);
20621af872cSJonathan Marek 
20721af872cSJonathan Marek 	for (i = 3; i <= 5; i++)
2086391030dSRob Clark 		if ((SZ_16K << i) == adreno_gpu->info->gmem)
20921af872cSJonathan Marek 			break;
21021af872cSJonathan Marek 	gpu_write(gpu, REG_A2XX_RB_EDRAM_INFO, i);
21121af872cSJonathan Marek 
21221af872cSJonathan Marek 	ret = adreno_hw_init(gpu);
21321af872cSJonathan Marek 	if (ret)
21421af872cSJonathan Marek 		return ret;
21521af872cSJonathan Marek 
216f6828e0cSJordan Crouse 	gpu_write(gpu, REG_AXXX_CP_RB_CNTL,
217f6828e0cSJordan Crouse 		MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE);
218f6828e0cSJordan Crouse 
219f6828e0cSJordan Crouse 	gpu_write(gpu, REG_AXXX_CP_RB_BASE, lower_32_bits(gpu->rb[0]->iova));
220f6828e0cSJordan Crouse 
22121af872cSJonathan Marek 	/* NOTE: PM4/micro-engine firmware registers look to be the same
22221af872cSJonathan Marek 	 * for a2xx and a3xx.. we could possibly push that part down to
22321af872cSJonathan Marek 	 * adreno_gpu base class.  Or push both PM4 and PFP but
22421af872cSJonathan Marek 	 * parameterize the pfp ucode addr/data registers..
22521af872cSJonathan Marek 	 */
22621af872cSJonathan Marek 
22721af872cSJonathan Marek 	/* Load PM4: */
22821af872cSJonathan Marek 	ptr = (uint32_t *)(adreno_gpu->fw[ADRENO_FW_PM4]->data);
22921af872cSJonathan Marek 	len = adreno_gpu->fw[ADRENO_FW_PM4]->size / 4;
23021af872cSJonathan Marek 	DBG("loading PM4 ucode version: %x", ptr[1]);
23121af872cSJonathan Marek 
23230229507SDmitry Baryshkov 	/*
23330229507SDmitry Baryshkov 	 * New firmware files seem to have GPU and firmware version in this
23430229507SDmitry Baryshkov 	 * word (0x20xxxx for A200, 0x220xxx for A220, 0x225xxx for A225).
23530229507SDmitry Baryshkov 	 * Older firmware files, which lack protection support, have 0 instead.
23630229507SDmitry Baryshkov 	 */
23730229507SDmitry Baryshkov 	if (ptr[1] == 0) {
23830229507SDmitry Baryshkov 		dev_warn(gpu->dev->dev,
23930229507SDmitry Baryshkov 			 "Legacy firmware detected, disabling protection support\n");
24030229507SDmitry Baryshkov 		a2xx_gpu->protection_disabled = true;
24130229507SDmitry Baryshkov 	}
24230229507SDmitry Baryshkov 
24321af872cSJonathan Marek 	gpu_write(gpu, REG_AXXX_CP_DEBUG,
24421af872cSJonathan Marek 			AXXX_CP_DEBUG_MIU_128BIT_WRITE_ENABLE);
24521af872cSJonathan Marek 	gpu_write(gpu, REG_AXXX_CP_ME_RAM_WADDR, 0);
24621af872cSJonathan Marek 	for (i = 1; i < len; i++)
24721af872cSJonathan Marek 		gpu_write(gpu, REG_AXXX_CP_ME_RAM_DATA, ptr[i]);
24821af872cSJonathan Marek 
24921af872cSJonathan Marek 	/* Load PFP: */
25021af872cSJonathan Marek 	ptr = (uint32_t *)(adreno_gpu->fw[ADRENO_FW_PFP]->data);
25121af872cSJonathan Marek 	len = adreno_gpu->fw[ADRENO_FW_PFP]->size / 4;
25221af872cSJonathan Marek 	DBG("loading PFP ucode version: %x", ptr[5]);
25321af872cSJonathan Marek 
25421af872cSJonathan Marek 	gpu_write(gpu, REG_A2XX_CP_PFP_UCODE_ADDR, 0);
25521af872cSJonathan Marek 	for (i = 1; i < len; i++)
25621af872cSJonathan Marek 		gpu_write(gpu, REG_A2XX_CP_PFP_UCODE_DATA, ptr[i]);
25721af872cSJonathan Marek 
25821af872cSJonathan Marek 	gpu_write(gpu, REG_AXXX_CP_QUEUE_THRESHOLDS, 0x000C0804);
25921af872cSJonathan Marek 
26021af872cSJonathan Marek 	/* clear ME_HALT to start micro engine */
26121af872cSJonathan Marek 	gpu_write(gpu, REG_AXXX_CP_ME_CNTL, 0);
26221af872cSJonathan Marek 
26321af872cSJonathan Marek 	return a2xx_me_init(gpu) ? 0 : -EINVAL;
26421af872cSJonathan Marek }
26521af872cSJonathan Marek 
a2xx_recover(struct msm_gpu * gpu)26621af872cSJonathan Marek static void a2xx_recover(struct msm_gpu *gpu)
26721af872cSJonathan Marek {
26821af872cSJonathan Marek 	int i;
26921af872cSJonathan Marek 
27021af872cSJonathan Marek 	adreno_dump_info(gpu);
27121af872cSJonathan Marek 
27221af872cSJonathan Marek 	for (i = 0; i < 8; i++) {
27321af872cSJonathan Marek 		printk("CP_SCRATCH_REG%d: %u\n", i,
27421af872cSJonathan Marek 			gpu_read(gpu, REG_AXXX_CP_SCRATCH_REG0 + i));
27521af872cSJonathan Marek 	}
27621af872cSJonathan Marek 
27721af872cSJonathan Marek 	/* dump registers before resetting gpu, if enabled: */
27821af872cSJonathan Marek 	if (hang_debug)
27921af872cSJonathan Marek 		a2xx_dump(gpu);
28021af872cSJonathan Marek 
28121af872cSJonathan Marek 	gpu_write(gpu, REG_A2XX_RBBM_SOFT_RESET, 1);
28221af872cSJonathan Marek 	gpu_read(gpu, REG_A2XX_RBBM_SOFT_RESET);
28321af872cSJonathan Marek 	gpu_write(gpu, REG_A2XX_RBBM_SOFT_RESET, 0);
28421af872cSJonathan Marek 	adreno_recover(gpu);
28521af872cSJonathan Marek }
28621af872cSJonathan Marek 
a2xx_destroy(struct msm_gpu * gpu)28721af872cSJonathan Marek static void a2xx_destroy(struct msm_gpu *gpu)
28821af872cSJonathan Marek {
28921af872cSJonathan Marek 	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
29021af872cSJonathan Marek 	struct a2xx_gpu *a2xx_gpu = to_a2xx_gpu(adreno_gpu);
29121af872cSJonathan Marek 
29221af872cSJonathan Marek 	DBG("%s", gpu->name);
29321af872cSJonathan Marek 
29421af872cSJonathan Marek 	adreno_gpu_cleanup(adreno_gpu);
29521af872cSJonathan Marek 
29621af872cSJonathan Marek 	kfree(a2xx_gpu);
29721af872cSJonathan Marek }
29821af872cSJonathan Marek 
a2xx_idle(struct msm_gpu * gpu)29921af872cSJonathan Marek static bool a2xx_idle(struct msm_gpu *gpu)
30021af872cSJonathan Marek {
30121af872cSJonathan Marek 	/* wait for ringbuffer to drain: */
30221af872cSJonathan Marek 	if (!adreno_idle(gpu, gpu->rb[0]))
30321af872cSJonathan Marek 		return false;
30421af872cSJonathan Marek 
30521af872cSJonathan Marek 	/* then wait for GPU to finish: */
30621af872cSJonathan Marek 	if (spin_until(!(gpu_read(gpu, REG_A2XX_RBBM_STATUS) &
30721af872cSJonathan Marek 			A2XX_RBBM_STATUS_GUI_ACTIVE))) {
30821af872cSJonathan Marek 		DRM_ERROR("%s: timeout waiting for GPU to idle!\n", gpu->name);
30921af872cSJonathan Marek 
31021af872cSJonathan Marek 		/* TODO maybe we need to reset GPU here to recover from hang? */
31121af872cSJonathan Marek 		return false;
31221af872cSJonathan Marek 	}
31321af872cSJonathan Marek 
31421af872cSJonathan Marek 	return true;
31521af872cSJonathan Marek }
31621af872cSJonathan Marek 
a2xx_irq(struct msm_gpu * gpu)31721af872cSJonathan Marek static irqreturn_t a2xx_irq(struct msm_gpu *gpu)
31821af872cSJonathan Marek {
31921af872cSJonathan Marek 	uint32_t mstatus, status;
32021af872cSJonathan Marek 
32121af872cSJonathan Marek 	mstatus = gpu_read(gpu, REG_A2XX_MASTER_INT_SIGNAL);
32221af872cSJonathan Marek 
32321af872cSJonathan Marek 	if (mstatus & A2XX_MASTER_INT_SIGNAL_MH_INT_STAT) {
32421af872cSJonathan Marek 		status = gpu_read(gpu, REG_A2XX_MH_INTERRUPT_STATUS);
32521af872cSJonathan Marek 
32621af872cSJonathan Marek 		dev_warn(gpu->dev->dev, "MH_INT: %08X\n", status);
32721af872cSJonathan Marek 		dev_warn(gpu->dev->dev, "MMU_PAGE_FAULT: %08X\n",
32821af872cSJonathan Marek 			gpu_read(gpu, REG_A2XX_MH_MMU_PAGE_FAULT));
32921af872cSJonathan Marek 
33021af872cSJonathan Marek 		gpu_write(gpu, REG_A2XX_MH_INTERRUPT_CLEAR, status);
33121af872cSJonathan Marek 	}
33221af872cSJonathan Marek 
33321af872cSJonathan Marek 	if (mstatus & A2XX_MASTER_INT_SIGNAL_CP_INT_STAT) {
33421af872cSJonathan Marek 		status = gpu_read(gpu, REG_AXXX_CP_INT_STATUS);
33521af872cSJonathan Marek 
33621af872cSJonathan Marek 		/* only RB_INT is expected */
33721af872cSJonathan Marek 		if (status & ~AXXX_CP_INT_CNTL_RB_INT_MASK)
33821af872cSJonathan Marek 			dev_warn(gpu->dev->dev, "CP_INT: %08X\n", status);
33921af872cSJonathan Marek 
34021af872cSJonathan Marek 		gpu_write(gpu, REG_AXXX_CP_INT_ACK, status);
34121af872cSJonathan Marek 	}
34221af872cSJonathan Marek 
34321af872cSJonathan Marek 	if (mstatus & A2XX_MASTER_INT_SIGNAL_RBBM_INT_STAT) {
34421af872cSJonathan Marek 		status = gpu_read(gpu, REG_A2XX_RBBM_INT_STATUS);
34521af872cSJonathan Marek 
34621af872cSJonathan Marek 		dev_warn(gpu->dev->dev, "RBBM_INT: %08X\n", status);
34721af872cSJonathan Marek 
34821af872cSJonathan Marek 		gpu_write(gpu, REG_A2XX_RBBM_INT_ACK, status);
34921af872cSJonathan Marek 	}
35021af872cSJonathan Marek 
35121af872cSJonathan Marek 	msm_gpu_retire(gpu);
35221af872cSJonathan Marek 
35321af872cSJonathan Marek 	return IRQ_HANDLED;
35421af872cSJonathan Marek }
35521af872cSJonathan Marek 
35621af872cSJonathan Marek static const unsigned int a200_registers[] = {
35721af872cSJonathan Marek 	0x0000, 0x0002, 0x0004, 0x000B, 0x003B, 0x003D, 0x0040, 0x0044,
35821af872cSJonathan Marek 	0x0046, 0x0047, 0x01C0, 0x01C1, 0x01C3, 0x01C8, 0x01D5, 0x01D9,
35921af872cSJonathan Marek 	0x01DC, 0x01DD, 0x01EA, 0x01EA, 0x01EE, 0x01F3, 0x01F6, 0x01F7,
36021af872cSJonathan Marek 	0x01FC, 0x01FF, 0x0391, 0x0392, 0x039B, 0x039E, 0x03B2, 0x03B5,
36121af872cSJonathan Marek 	0x03B7, 0x03B7, 0x03F8, 0x03FB, 0x0440, 0x0440, 0x0443, 0x0444,
36221af872cSJonathan Marek 	0x044B, 0x044B, 0x044D, 0x044F, 0x0452, 0x0452, 0x0454, 0x045B,
36321af872cSJonathan Marek 	0x047F, 0x047F, 0x0578, 0x0587, 0x05C9, 0x05C9, 0x05D0, 0x05D0,
36421af872cSJonathan Marek 	0x0601, 0x0604, 0x0606, 0x0609, 0x060B, 0x060E, 0x0613, 0x0614,
36521af872cSJonathan Marek 	0x0A29, 0x0A2B, 0x0A2F, 0x0A31, 0x0A40, 0x0A43, 0x0A45, 0x0A45,
36621af872cSJonathan Marek 	0x0A4E, 0x0A4F, 0x0C2C, 0x0C2C, 0x0C30, 0x0C30, 0x0C38, 0x0C3C,
36721af872cSJonathan Marek 	0x0C40, 0x0C40, 0x0C44, 0x0C44, 0x0C80, 0x0C86, 0x0C88, 0x0C94,
36821af872cSJonathan Marek 	0x0C99, 0x0C9A, 0x0CA4, 0x0CA5, 0x0D00, 0x0D03, 0x0D06, 0x0D06,
36921af872cSJonathan Marek 	0x0D08, 0x0D0B, 0x0D34, 0x0D35, 0x0DAE, 0x0DC1, 0x0DC8, 0x0DD4,
37021af872cSJonathan Marek 	0x0DD8, 0x0DD9, 0x0E00, 0x0E00, 0x0E02, 0x0E04, 0x0E17, 0x0E1E,
37121af872cSJonathan Marek 	0x0EC0, 0x0EC9, 0x0ECB, 0x0ECC, 0x0ED0, 0x0ED0, 0x0ED4, 0x0ED7,
37221af872cSJonathan Marek 	0x0EE0, 0x0EE2, 0x0F01, 0x0F02, 0x0F0C, 0x0F0C, 0x0F0E, 0x0F12,
37321af872cSJonathan Marek 	0x0F26, 0x0F2A, 0x0F2C, 0x0F2C, 0x2000, 0x2002, 0x2006, 0x200F,
37421af872cSJonathan Marek 	0x2080, 0x2082, 0x2100, 0x2109, 0x210C, 0x2114, 0x2180, 0x2184,
37521af872cSJonathan Marek 	0x21F5, 0x21F7, 0x2200, 0x2208, 0x2280, 0x2283, 0x2293, 0x2294,
37621af872cSJonathan Marek 	0x2300, 0x2308, 0x2312, 0x2312, 0x2316, 0x231D, 0x2324, 0x2326,
37721af872cSJonathan Marek 	0x2380, 0x2383, 0x2400, 0x2402, 0x2406, 0x240F, 0x2480, 0x2482,
37821af872cSJonathan Marek 	0x2500, 0x2509, 0x250C, 0x2514, 0x2580, 0x2584, 0x25F5, 0x25F7,
37921af872cSJonathan Marek 	0x2600, 0x2608, 0x2680, 0x2683, 0x2693, 0x2694, 0x2700, 0x2708,
38021af872cSJonathan Marek 	0x2712, 0x2712, 0x2716, 0x271D, 0x2724, 0x2726, 0x2780, 0x2783,
38121af872cSJonathan Marek 	0x4000, 0x4003, 0x4800, 0x4805, 0x4900, 0x4900, 0x4908, 0x4908,
38221af872cSJonathan Marek 	~0   /* sentinel */
38321af872cSJonathan Marek };
38421af872cSJonathan Marek 
38521af872cSJonathan Marek static const unsigned int a220_registers[] = {
38621af872cSJonathan Marek 	0x0000, 0x0002, 0x0004, 0x000B, 0x003B, 0x003D, 0x0040, 0x0044,
38721af872cSJonathan Marek 	0x0046, 0x0047, 0x01C0, 0x01C1, 0x01C3, 0x01C8, 0x01D5, 0x01D9,
38821af872cSJonathan Marek 	0x01DC, 0x01DD, 0x01EA, 0x01EA, 0x01EE, 0x01F3, 0x01F6, 0x01F7,
38921af872cSJonathan Marek 	0x01FC, 0x01FF, 0x0391, 0x0392, 0x039B, 0x039E, 0x03B2, 0x03B5,
39021af872cSJonathan Marek 	0x03B7, 0x03B7, 0x03F8, 0x03FB, 0x0440, 0x0440, 0x0443, 0x0444,
39121af872cSJonathan Marek 	0x044B, 0x044B, 0x044D, 0x044F, 0x0452, 0x0452, 0x0454, 0x045B,
39221af872cSJonathan Marek 	0x047F, 0x047F, 0x0578, 0x0587, 0x05C9, 0x05C9, 0x05D0, 0x05D0,
39321af872cSJonathan Marek 	0x0601, 0x0604, 0x0606, 0x0609, 0x060B, 0x060E, 0x0613, 0x0614,
39421af872cSJonathan Marek 	0x0A29, 0x0A2B, 0x0A2F, 0x0A31, 0x0A40, 0x0A40, 0x0A42, 0x0A43,
39521af872cSJonathan Marek 	0x0A45, 0x0A45, 0x0A4E, 0x0A4F, 0x0C30, 0x0C30, 0x0C38, 0x0C39,
39621af872cSJonathan Marek 	0x0C3C, 0x0C3C, 0x0C80, 0x0C81, 0x0C88, 0x0C93, 0x0D00, 0x0D03,
39721af872cSJonathan Marek 	0x0D05, 0x0D06, 0x0D08, 0x0D0B, 0x0D34, 0x0D35, 0x0DAE, 0x0DC1,
39821af872cSJonathan Marek 	0x0DC8, 0x0DD4, 0x0DD8, 0x0DD9, 0x0E00, 0x0E00, 0x0E02, 0x0E04,
39921af872cSJonathan Marek 	0x0E17, 0x0E1E, 0x0EC0, 0x0EC9, 0x0ECB, 0x0ECC, 0x0ED0, 0x0ED0,
40021af872cSJonathan Marek 	0x0ED4, 0x0ED7, 0x0EE0, 0x0EE2, 0x0F01, 0x0F02, 0x2000, 0x2002,
40121af872cSJonathan Marek 	0x2006, 0x200F, 0x2080, 0x2082, 0x2100, 0x2102, 0x2104, 0x2109,
40221af872cSJonathan Marek 	0x210C, 0x2114, 0x2180, 0x2184, 0x21F5, 0x21F7, 0x2200, 0x2202,
40321af872cSJonathan Marek 	0x2204, 0x2204, 0x2208, 0x2208, 0x2280, 0x2282, 0x2294, 0x2294,
40421af872cSJonathan Marek 	0x2300, 0x2308, 0x2309, 0x230A, 0x2312, 0x2312, 0x2316, 0x2316,
40521af872cSJonathan Marek 	0x2318, 0x231D, 0x2324, 0x2326, 0x2380, 0x2383, 0x2400, 0x2402,
40621af872cSJonathan Marek 	0x2406, 0x240F, 0x2480, 0x2482, 0x2500, 0x2502, 0x2504, 0x2509,
40721af872cSJonathan Marek 	0x250C, 0x2514, 0x2580, 0x2584, 0x25F5, 0x25F7, 0x2600, 0x2602,
40821af872cSJonathan Marek 	0x2604, 0x2606, 0x2608, 0x2608, 0x2680, 0x2682, 0x2694, 0x2694,
40921af872cSJonathan Marek 	0x2700, 0x2708, 0x2712, 0x2712, 0x2716, 0x2716, 0x2718, 0x271D,
41021af872cSJonathan Marek 	0x2724, 0x2726, 0x2780, 0x2783, 0x4000, 0x4003, 0x4800, 0x4805,
41121af872cSJonathan Marek 	0x4900, 0x4900, 0x4908, 0x4908,
41221af872cSJonathan Marek 	~0   /* sentinel */
41321af872cSJonathan Marek };
41421af872cSJonathan Marek 
41521af872cSJonathan Marek static const unsigned int a225_registers[] = {
41621af872cSJonathan Marek 	0x0000, 0x0002, 0x0004, 0x000B, 0x003B, 0x003D, 0x0040, 0x0044,
41721af872cSJonathan Marek 	0x0046, 0x0047, 0x013C, 0x013C, 0x0140, 0x014F, 0x01C0, 0x01C1,
41821af872cSJonathan Marek 	0x01C3, 0x01C8, 0x01D5, 0x01D9, 0x01DC, 0x01DD, 0x01EA, 0x01EA,
41921af872cSJonathan Marek 	0x01EE, 0x01F3, 0x01F6, 0x01F7, 0x01FC, 0x01FF, 0x0391, 0x0392,
42021af872cSJonathan Marek 	0x039B, 0x039E, 0x03B2, 0x03B5, 0x03B7, 0x03B7, 0x03F8, 0x03FB,
42121af872cSJonathan Marek 	0x0440, 0x0440, 0x0443, 0x0444, 0x044B, 0x044B, 0x044D, 0x044F,
42221af872cSJonathan Marek 	0x0452, 0x0452, 0x0454, 0x045B, 0x047F, 0x047F, 0x0578, 0x0587,
42321af872cSJonathan Marek 	0x05C9, 0x05C9, 0x05D0, 0x05D0, 0x0601, 0x0604, 0x0606, 0x0609,
42421af872cSJonathan Marek 	0x060B, 0x060E, 0x0613, 0x0614, 0x0A29, 0x0A2B, 0x0A2F, 0x0A31,
42521af872cSJonathan Marek 	0x0A40, 0x0A40, 0x0A42, 0x0A43, 0x0A45, 0x0A45, 0x0A4E, 0x0A4F,
42621af872cSJonathan Marek 	0x0C01, 0x0C1D, 0x0C30, 0x0C30, 0x0C38, 0x0C39, 0x0C3C, 0x0C3C,
42721af872cSJonathan Marek 	0x0C80, 0x0C81, 0x0C88, 0x0C93, 0x0D00, 0x0D03, 0x0D05, 0x0D06,
42821af872cSJonathan Marek 	0x0D08, 0x0D0B, 0x0D34, 0x0D35, 0x0DAE, 0x0DC1, 0x0DC8, 0x0DD4,
42921af872cSJonathan Marek 	0x0DD8, 0x0DD9, 0x0E00, 0x0E00, 0x0E02, 0x0E04, 0x0E17, 0x0E1E,
43021af872cSJonathan Marek 	0x0EC0, 0x0EC9, 0x0ECB, 0x0ECC, 0x0ED0, 0x0ED0, 0x0ED4, 0x0ED7,
43121af872cSJonathan Marek 	0x0EE0, 0x0EE2, 0x0F01, 0x0F02, 0x2000, 0x200F, 0x2080, 0x2082,
43221af872cSJonathan Marek 	0x2100, 0x2109, 0x210C, 0x2114, 0x2180, 0x2184, 0x21F5, 0x21F7,
43321af872cSJonathan Marek 	0x2200, 0x2202, 0x2204, 0x2206, 0x2208, 0x2210, 0x2220, 0x2222,
43421af872cSJonathan Marek 	0x2280, 0x2282, 0x2294, 0x2294, 0x2297, 0x2297, 0x2300, 0x230A,
43521af872cSJonathan Marek 	0x2312, 0x2312, 0x2315, 0x2316, 0x2318, 0x231D, 0x2324, 0x2326,
43621af872cSJonathan Marek 	0x2340, 0x2357, 0x2360, 0x2360, 0x2380, 0x2383, 0x2400, 0x240F,
43721af872cSJonathan Marek 	0x2480, 0x2482, 0x2500, 0x2509, 0x250C, 0x2514, 0x2580, 0x2584,
43821af872cSJonathan Marek 	0x25F5, 0x25F7, 0x2600, 0x2602, 0x2604, 0x2606, 0x2608, 0x2610,
43921af872cSJonathan Marek 	0x2620, 0x2622, 0x2680, 0x2682, 0x2694, 0x2694, 0x2697, 0x2697,
44021af872cSJonathan Marek 	0x2700, 0x270A, 0x2712, 0x2712, 0x2715, 0x2716, 0x2718, 0x271D,
44121af872cSJonathan Marek 	0x2724, 0x2726, 0x2740, 0x2757, 0x2760, 0x2760, 0x2780, 0x2783,
44221af872cSJonathan Marek 	0x4000, 0x4003, 0x4800, 0x4806, 0x4808, 0x4808, 0x4900, 0x4900,
44321af872cSJonathan Marek 	0x4908, 0x4908,
44421af872cSJonathan Marek 	~0   /* sentinel */
44521af872cSJonathan Marek };
44621af872cSJonathan Marek 
44721af872cSJonathan Marek /* would be nice to not have to duplicate the _show() stuff with printk(): */
a2xx_dump(struct msm_gpu * gpu)44821af872cSJonathan Marek static void a2xx_dump(struct msm_gpu *gpu)
44921af872cSJonathan Marek {
45021af872cSJonathan Marek 	printk("status:   %08x\n",
45121af872cSJonathan Marek 			gpu_read(gpu, REG_A2XX_RBBM_STATUS));
45221af872cSJonathan Marek 	adreno_dump(gpu);
45321af872cSJonathan Marek }
45421af872cSJonathan Marek 
a2xx_gpu_state_get(struct msm_gpu * gpu)45521af872cSJonathan Marek static struct msm_gpu_state *a2xx_gpu_state_get(struct msm_gpu *gpu)
45621af872cSJonathan Marek {
45721af872cSJonathan Marek 	struct msm_gpu_state *state = kzalloc(sizeof(*state), GFP_KERNEL);
45821af872cSJonathan Marek 
45921af872cSJonathan Marek 	if (!state)
46021af872cSJonathan Marek 		return ERR_PTR(-ENOMEM);
46121af872cSJonathan Marek 
46221af872cSJonathan Marek 	adreno_gpu_state_get(gpu, state);
46321af872cSJonathan Marek 
46421af872cSJonathan Marek 	state->rbbm_status = gpu_read(gpu, REG_A2XX_RBBM_STATUS);
46521af872cSJonathan Marek 
46621af872cSJonathan Marek 	return state;
46721af872cSJonathan Marek }
46821af872cSJonathan Marek 
469ccac7ce3SJordan Crouse static struct msm_gem_address_space *
a2xx_create_address_space(struct msm_gpu * gpu,struct platform_device * pdev)470ccac7ce3SJordan Crouse a2xx_create_address_space(struct msm_gpu *gpu, struct platform_device *pdev)
471ccac7ce3SJordan Crouse {
472ccac7ce3SJordan Crouse 	struct msm_mmu *mmu = msm_gpummu_new(&pdev->dev, gpu);
473ccac7ce3SJordan Crouse 	struct msm_gem_address_space *aspace;
474ccac7ce3SJordan Crouse 
475ccac7ce3SJordan Crouse 	aspace = msm_gem_address_space_create(mmu, "gpu", SZ_16M,
47630480e6eSJordan Crouse 		0xfff * SZ_64K);
477ccac7ce3SJordan Crouse 
478ccac7ce3SJordan Crouse 	if (IS_ERR(aspace) && !IS_ERR(mmu))
479ccac7ce3SJordan Crouse 		mmu->funcs->destroy(mmu);
480ccac7ce3SJordan Crouse 
481ccac7ce3SJordan Crouse 	return aspace;
482ccac7ce3SJordan Crouse }
483ccac7ce3SJordan Crouse 
a2xx_get_rptr(struct msm_gpu * gpu,struct msm_ringbuffer * ring)4842fb7487aSJordan Crouse static u32 a2xx_get_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
4852fb7487aSJordan Crouse {
4862fb7487aSJordan Crouse 	ring->memptrs->rptr = gpu_read(gpu, REG_AXXX_CP_RB_RPTR);
4872fb7487aSJordan Crouse 	return ring->memptrs->rptr;
4882fb7487aSJordan Crouse }
48921af872cSJonathan Marek 
49021af872cSJonathan Marek static const struct adreno_gpu_funcs funcs = {
49121af872cSJonathan Marek 	.base = {
49221af872cSJonathan Marek 		.get_param = adreno_get_param,
493f7ddbf55SRob Clark 		.set_param = adreno_set_param,
49421af872cSJonathan Marek 		.hw_init = a2xx_hw_init,
49521af872cSJonathan Marek 		.pm_suspend = msm_gpu_pm_suspend,
49621af872cSJonathan Marek 		.pm_resume = msm_gpu_pm_resume,
49721af872cSJonathan Marek 		.recover = a2xx_recover,
4982fb7487aSJordan Crouse 		.submit = a2xx_submit,
49921af872cSJonathan Marek 		.active_ring = adreno_active_ring,
50021af872cSJonathan Marek 		.irq = a2xx_irq,
50121af872cSJonathan Marek 		.destroy = a2xx_destroy,
50221af872cSJonathan Marek #if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP)
50321af872cSJonathan Marek 		.show = adreno_show,
50421af872cSJonathan Marek #endif
50521af872cSJonathan Marek 		.gpu_state_get = a2xx_gpu_state_get,
50621af872cSJonathan Marek 		.gpu_state_put = adreno_gpu_state_put,
507ccac7ce3SJordan Crouse 		.create_address_space = a2xx_create_address_space,
5082fb7487aSJordan Crouse 		.get_rptr = a2xx_get_rptr,
50921af872cSJonathan Marek 	},
51021af872cSJonathan Marek };
51121af872cSJonathan Marek 
51221af872cSJonathan Marek static const struct msm_gpu_perfcntr perfcntrs[] = {
51321af872cSJonathan Marek /* TODO */
51421af872cSJonathan Marek };
51521af872cSJonathan Marek 
a2xx_gpu_init(struct drm_device * dev)51621af872cSJonathan Marek struct msm_gpu *a2xx_gpu_init(struct drm_device *dev)
51721af872cSJonathan Marek {
51821af872cSJonathan Marek 	struct a2xx_gpu *a2xx_gpu = NULL;
51921af872cSJonathan Marek 	struct adreno_gpu *adreno_gpu;
52021af872cSJonathan Marek 	struct msm_gpu *gpu;
52121af872cSJonathan Marek 	struct msm_drm_private *priv = dev->dev_private;
52221af872cSJonathan Marek 	struct platform_device *pdev = priv->gpu_pdev;
52321af872cSJonathan Marek 	int ret;
52421af872cSJonathan Marek 
52521af872cSJonathan Marek 	if (!pdev) {
52621af872cSJonathan Marek 		dev_err(dev->dev, "no a2xx device\n");
52721af872cSJonathan Marek 		ret = -ENXIO;
52821af872cSJonathan Marek 		goto fail;
52921af872cSJonathan Marek 	}
53021af872cSJonathan Marek 
53121af872cSJonathan Marek 	a2xx_gpu = kzalloc(sizeof(*a2xx_gpu), GFP_KERNEL);
53221af872cSJonathan Marek 	if (!a2xx_gpu) {
53321af872cSJonathan Marek 		ret = -ENOMEM;
53421af872cSJonathan Marek 		goto fail;
53521af872cSJonathan Marek 	}
53621af872cSJonathan Marek 
53721af872cSJonathan Marek 	adreno_gpu = &a2xx_gpu->base;
53821af872cSJonathan Marek 	gpu = &adreno_gpu->base;
53921af872cSJonathan Marek 
54021af872cSJonathan Marek 	gpu->perfcntrs = perfcntrs;
54121af872cSJonathan Marek 	gpu->num_perfcntrs = ARRAY_SIZE(perfcntrs);
54221af872cSJonathan Marek 
543*db07ce5dSFabio Estevam 	ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1);
544*db07ce5dSFabio Estevam 	if (ret)
545*db07ce5dSFabio Estevam 		goto fail;
546*db07ce5dSFabio Estevam 
54721af872cSJonathan Marek 	if (adreno_is_a20x(adreno_gpu))
54821af872cSJonathan Marek 		adreno_gpu->registers = a200_registers;
54921af872cSJonathan Marek 	else if (adreno_is_a225(adreno_gpu))
55021af872cSJonathan Marek 		adreno_gpu->registers = a225_registers;
55121af872cSJonathan Marek 	else
55221af872cSJonathan Marek 		adreno_gpu->registers = a220_registers;
55321af872cSJonathan Marek 
55421af872cSJonathan Marek 	if (!gpu->aspace) {
55521af872cSJonathan Marek 		dev_err(dev->dev, "No memory protection without MMU\n");
5563f7759e7SIskren Chernev 		if (!allow_vram_carveout) {
55721af872cSJonathan Marek 			ret = -ENXIO;
55821af872cSJonathan Marek 			goto fail;
55921af872cSJonathan Marek 		}
5603f7759e7SIskren Chernev 	}
56121af872cSJonathan Marek 
56221af872cSJonathan Marek 	return gpu;
56321af872cSJonathan Marek 
56421af872cSJonathan Marek fail:
56521af872cSJonathan Marek 	if (a2xx_gpu)
56621af872cSJonathan Marek 		a2xx_destroy(&a2xx_gpu->base.base);
56721af872cSJonathan Marek 
56821af872cSJonathan Marek 	return ERR_PTR(ret);
56921af872cSJonathan Marek }
570