xref: /linux/drivers/gpu/drm/msm/adreno/a4xx_gpu.c (revision 97fb5e8d9b57f10f294303c9a5d1bd033eded6bf)
1*97fb5e8dSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
223bd62fdSAravind Ganesan /* Copyright (c) 2014 The Linux Foundation. All rights reserved.
323bd62fdSAravind Ganesan  */
423bd62fdSAravind Ganesan #include "a4xx_gpu.h"
523bd62fdSAravind Ganesan #ifdef CONFIG_MSM_OCMEM
623bd62fdSAravind Ganesan #  include <soc/qcom/ocmem.h>
723bd62fdSAravind Ganesan #endif
823bd62fdSAravind Ganesan 
923bd62fdSAravind Ganesan #define A4XX_INT0_MASK \
1023bd62fdSAravind Ganesan 	(A4XX_INT0_RBBM_AHB_ERROR |        \
1123bd62fdSAravind Ganesan 	 A4XX_INT0_RBBM_ATB_BUS_OVERFLOW | \
1223bd62fdSAravind Ganesan 	 A4XX_INT0_CP_T0_PACKET_IN_IB |    \
1323bd62fdSAravind Ganesan 	 A4XX_INT0_CP_OPCODE_ERROR |       \
1423bd62fdSAravind Ganesan 	 A4XX_INT0_CP_RESERVED_BIT_ERROR | \
1523bd62fdSAravind Ganesan 	 A4XX_INT0_CP_HW_FAULT |           \
1623bd62fdSAravind Ganesan 	 A4XX_INT0_CP_IB1_INT |            \
1723bd62fdSAravind Ganesan 	 A4XX_INT0_CP_IB2_INT |            \
1823bd62fdSAravind Ganesan 	 A4XX_INT0_CP_RB_INT |             \
1923bd62fdSAravind Ganesan 	 A4XX_INT0_CP_REG_PROTECT_FAULT |  \
2023bd62fdSAravind Ganesan 	 A4XX_INT0_CP_AHB_ERROR_HALT |     \
2179d57bf6SBjorn Andersson 	 A4XX_INT0_CACHE_FLUSH_TS |        \
2223bd62fdSAravind Ganesan 	 A4XX_INT0_UCHE_OOB_ACCESS)
2323bd62fdSAravind Ganesan 
2423bd62fdSAravind Ganesan extern bool hang_debug;
2523bd62fdSAravind Ganesan static void a4xx_dump(struct msm_gpu *gpu);
26e895c7bdSJordan Crouse static bool a4xx_idle(struct msm_gpu *gpu);
2723bd62fdSAravind Ganesan 
2823bd62fdSAravind Ganesan /*
2923bd62fdSAravind Ganesan  * a4xx_enable_hwcg() - Program the clock control registers
3023bd62fdSAravind Ganesan  * @device: The adreno device pointer
3123bd62fdSAravind Ganesan  */
3223bd62fdSAravind Ganesan static void a4xx_enable_hwcg(struct msm_gpu *gpu)
3323bd62fdSAravind Ganesan {
3423bd62fdSAravind Ganesan 	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
3523bd62fdSAravind Ganesan 	unsigned int i;
3623bd62fdSAravind Ganesan 	for (i = 0; i < 4; i++)
3723bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_TP(i), 0x02222202);
3823bd62fdSAravind Ganesan 	for (i = 0; i < 4; i++)
3923bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL2_TP(i), 0x00002222);
4023bd62fdSAravind Ganesan 	for (i = 0; i < 4; i++)
4123bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_TP(i), 0x0E739CE7);
4223bd62fdSAravind Ganesan 	for (i = 0; i < 4; i++)
4323bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_TP(i), 0x00111111);
4423bd62fdSAravind Ganesan 	for (i = 0; i < 4; i++)
4523bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_SP(i), 0x22222222);
4623bd62fdSAravind Ganesan 	for (i = 0; i < 4; i++)
4723bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL2_SP(i), 0x00222222);
4823bd62fdSAravind Ganesan 	for (i = 0; i < 4; i++)
4923bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_SP(i), 0x00000104);
5023bd62fdSAravind Ganesan 	for (i = 0; i < 4; i++)
5123bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_SP(i), 0x00000081);
5223bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_UCHE, 0x22222222);
5323bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL2_UCHE, 0x02222222);
5423bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL3_UCHE, 0x00000000);
5523bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL4_UCHE, 0x00000000);
5623bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_UCHE, 0x00004444);
5723bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_UCHE, 0x00001112);
5823bd62fdSAravind Ganesan 	for (i = 0; i < 4; i++)
5923bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_RB(i), 0x22222222);
6023bd62fdSAravind Ganesan 
6123bd62fdSAravind Ganesan 	/* Disable L1 clocking in A420 due to CCU issues with it */
6223bd62fdSAravind Ganesan 	for (i = 0; i < 4; i++) {
6323bd62fdSAravind Ganesan 		if (adreno_is_a420(adreno_gpu)) {
6423bd62fdSAravind Ganesan 			gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL2_RB(i),
6523bd62fdSAravind Ganesan 					0x00002020);
6623bd62fdSAravind Ganesan 		} else {
6723bd62fdSAravind Ganesan 			gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL2_RB(i),
6823bd62fdSAravind Ganesan 					0x00022020);
6923bd62fdSAravind Ganesan 		}
7023bd62fdSAravind Ganesan 	}
7123bd62fdSAravind Ganesan 
7223bd62fdSAravind Ganesan 	for (i = 0; i < 4; i++) {
7323bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_MARB_CCU(i),
7423bd62fdSAravind Ganesan 				0x00000922);
7523bd62fdSAravind Ganesan 	}
7623bd62fdSAravind Ganesan 
7723bd62fdSAravind Ganesan 	for (i = 0; i < 4; i++) {
7823bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_RB_MARB_CCU(i),
7923bd62fdSAravind Ganesan 				0x00000000);
8023bd62fdSAravind Ganesan 	}
8123bd62fdSAravind Ganesan 
8223bd62fdSAravind Ganesan 	for (i = 0; i < 4; i++) {
8323bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_RB_MARB_CCU_L1(i),
8423bd62fdSAravind Ganesan 				0x00000001);
8523bd62fdSAravind Ganesan 	}
8623bd62fdSAravind Ganesan 
8723bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_CLOCK_MODE_GPC, 0x02222222);
8823bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_GPC, 0x04100104);
8923bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_GPC, 0x00022222);
9023bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_COM_DCOM, 0x00000022);
9123bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_COM_DCOM, 0x0000010F);
9223bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_COM_DCOM, 0x00000022);
9323bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_TSE_RAS_RBBM, 0x00222222);
9423bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00004104);
9523bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00000222);
9623bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_HLSQ , 0x00000000);
9723bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_HLSQ, 0x00000000);
98357ff00bSCraig Stout 	gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_HLSQ, 0x00220000);
99357ff00bSCraig Stout 	/* Early A430's have a timing issue with SP/TP power collapse;
100357ff00bSCraig Stout 	   disabling HW clock gating prevents it. */
101357ff00bSCraig Stout 	if (adreno_is_a430(adreno_gpu) && adreno_gpu->rev.patchid < 2)
102357ff00bSCraig Stout 		gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL, 0);
103357ff00bSCraig Stout 	else
10423bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL, 0xAAAAAAAA);
10523bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL2, 0);
10623bd62fdSAravind Ganesan }
10723bd62fdSAravind Ganesan 
108357ff00bSCraig Stout 
109c4a8d475SJordan Crouse static bool a4xx_me_init(struct msm_gpu *gpu)
11023bd62fdSAravind Ganesan {
111f97decacSJordan Crouse 	struct msm_ringbuffer *ring = gpu->rb[0];
11223bd62fdSAravind Ganesan 
11323bd62fdSAravind Ganesan 	OUT_PKT3(ring, CP_ME_INIT, 17);
11423bd62fdSAravind Ganesan 	OUT_RING(ring, 0x000003f7);
11523bd62fdSAravind Ganesan 	OUT_RING(ring, 0x00000000);
11623bd62fdSAravind Ganesan 	OUT_RING(ring, 0x00000000);
11723bd62fdSAravind Ganesan 	OUT_RING(ring, 0x00000000);
11823bd62fdSAravind Ganesan 	OUT_RING(ring, 0x00000080);
11923bd62fdSAravind Ganesan 	OUT_RING(ring, 0x00000100);
12023bd62fdSAravind Ganesan 	OUT_RING(ring, 0x00000180);
12123bd62fdSAravind Ganesan 	OUT_RING(ring, 0x00006600);
12223bd62fdSAravind Ganesan 	OUT_RING(ring, 0x00000150);
12323bd62fdSAravind Ganesan 	OUT_RING(ring, 0x0000014e);
12423bd62fdSAravind Ganesan 	OUT_RING(ring, 0x00000154);
12523bd62fdSAravind Ganesan 	OUT_RING(ring, 0x00000001);
12623bd62fdSAravind Ganesan 	OUT_RING(ring, 0x00000000);
12723bd62fdSAravind Ganesan 	OUT_RING(ring, 0x00000000);
12823bd62fdSAravind Ganesan 	OUT_RING(ring, 0x00000000);
12923bd62fdSAravind Ganesan 	OUT_RING(ring, 0x00000000);
13023bd62fdSAravind Ganesan 	OUT_RING(ring, 0x00000000);
13123bd62fdSAravind Ganesan 
132f97decacSJordan Crouse 	gpu->funcs->flush(gpu, ring);
133e895c7bdSJordan Crouse 	return a4xx_idle(gpu);
13423bd62fdSAravind Ganesan }
13523bd62fdSAravind Ganesan 
13623bd62fdSAravind Ganesan static int a4xx_hw_init(struct msm_gpu *gpu)
13723bd62fdSAravind Ganesan {
13823bd62fdSAravind Ganesan 	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
13923bd62fdSAravind Ganesan 	struct a4xx_gpu *a4xx_gpu = to_a4xx_gpu(adreno_gpu);
14023bd62fdSAravind Ganesan 	uint32_t *ptr, len;
14123bd62fdSAravind Ganesan 	int i, ret;
14223bd62fdSAravind Ganesan 
143357ff00bSCraig Stout 	if (adreno_is_a420(adreno_gpu)) {
14423bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_VBIF_ABIT_SORT, 0x0001001F);
14523bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_VBIF_ABIT_SORT_CONF, 0x000000A4);
14623bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_VBIF_GATE_OFF_WRREQ_EN, 0x00000001);
14723bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_VBIF_IN_RD_LIM_CONF0, 0x18181818);
14823bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_VBIF_IN_RD_LIM_CONF1, 0x00000018);
14923bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_VBIF_IN_WR_LIM_CONF0, 0x18181818);
15023bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_VBIF_IN_WR_LIM_CONF1, 0x00000018);
15123bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x00000003);
152357ff00bSCraig Stout 	} else if (adreno_is_a430(adreno_gpu)) {
153357ff00bSCraig Stout 		gpu_write(gpu, REG_A4XX_VBIF_GATE_OFF_WRREQ_EN, 0x00000001);
154357ff00bSCraig Stout 		gpu_write(gpu, REG_A4XX_VBIF_IN_RD_LIM_CONF0, 0x18181818);
155357ff00bSCraig Stout 		gpu_write(gpu, REG_A4XX_VBIF_IN_RD_LIM_CONF1, 0x00000018);
156357ff00bSCraig Stout 		gpu_write(gpu, REG_A4XX_VBIF_IN_WR_LIM_CONF0, 0x18181818);
157357ff00bSCraig Stout 		gpu_write(gpu, REG_A4XX_VBIF_IN_WR_LIM_CONF1, 0x00000018);
158357ff00bSCraig Stout 		gpu_write(gpu, REG_A4XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x00000003);
15923bd62fdSAravind Ganesan 	} else {
16023bd62fdSAravind Ganesan 		BUG();
16123bd62fdSAravind Ganesan 	}
16223bd62fdSAravind Ganesan 
16323bd62fdSAravind Ganesan 	/* Make all blocks contribute to the GPU BUSY perf counter */
16423bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_GPU_BUSY_MASKED, 0xffffffff);
16523bd62fdSAravind Ganesan 
16623bd62fdSAravind Ganesan 	/* Tune the hystersis counters for SP and CP idle detection */
16723bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_SP_HYST_CNT, 0x10);
16823bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_WAIT_IDLE_CLOCKS_CTL, 0x10);
16923bd62fdSAravind Ganesan 
170357ff00bSCraig Stout 	if (adreno_is_a430(adreno_gpu)) {
171357ff00bSCraig Stout 		gpu_write(gpu, REG_A4XX_RBBM_WAIT_IDLE_CLOCKS_CTL2, 0x30);
172357ff00bSCraig Stout 	}
173357ff00bSCraig Stout 
17423bd62fdSAravind Ganesan 	 /* Enable the RBBM error reporting bits */
17523bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_AHB_CTL0, 0x00000001);
17623bd62fdSAravind Ganesan 
17723bd62fdSAravind Ganesan 	/* Enable AHB error reporting*/
17823bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_AHB_CTL1, 0xa6ffffff);
17923bd62fdSAravind Ganesan 
18023bd62fdSAravind Ganesan 	/* Enable power counters*/
18123bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_RBBM_CTL, 0x00000030);
18223bd62fdSAravind Ganesan 
18323bd62fdSAravind Ganesan 	/*
18423bd62fdSAravind Ganesan 	 * Turn on hang detection - this spews a lot of useful information
18523bd62fdSAravind Ganesan 	 * into the RBBM registers on a hang:
18623bd62fdSAravind Ganesan 	 */
18723bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_INTERFACE_HANG_INT_CTL,
18823bd62fdSAravind Ganesan 			(1 << 30) | 0xFFFF);
18923bd62fdSAravind Ganesan 
19023bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RB_GMEM_BASE_ADDR,
19123bd62fdSAravind Ganesan 			(unsigned int)(a4xx_gpu->ocmem_base >> 14));
19223bd62fdSAravind Ganesan 
19323bd62fdSAravind Ganesan 	/* Turn on performance counters: */
19423bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_PERFCTR_CTL, 0x01);
19523bd62fdSAravind Ganesan 
1966c77d1abSRob Clark 	/* use the first CP counter for timestamp queries.. userspace may set
1976c77d1abSRob Clark 	 * this as well but it selects the same counter/countable:
1986c77d1abSRob Clark 	 */
1996c77d1abSRob Clark 	gpu_write(gpu, REG_A4XX_CP_PERFCTR_CP_SEL_0, CP_ALWAYS_COUNT);
2006c77d1abSRob Clark 
201357ff00bSCraig Stout 	if (adreno_is_a430(adreno_gpu))
202357ff00bSCraig Stout 		gpu_write(gpu, REG_A4XX_UCHE_CACHE_WAYS_VFD, 0x07);
203357ff00bSCraig Stout 
20423bd62fdSAravind Ganesan 	/* Disable L2 bypass to avoid UCHE out of bounds errors */
20523bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_UCHE_TRAP_BASE_LO, 0xffff0000);
20623bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_UCHE_TRAP_BASE_HI, 0xffff0000);
20723bd62fdSAravind Ganesan 
20823bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_CP_DEBUG, (1 << 25) |
20923bd62fdSAravind Ganesan 			(adreno_is_a420(adreno_gpu) ? (1 << 29) : 0));
21023bd62fdSAravind Ganesan 
211357ff00bSCraig Stout 	/* On A430 enable SP regfile sleep for power savings */
212357ff00bSCraig Stout 	/* TODO downstream does this for !420, so maybe applies for 405 too? */
213357ff00bSCraig Stout 	if (!adreno_is_a420(adreno_gpu)) {
214357ff00bSCraig Stout 		gpu_write(gpu, REG_A4XX_RBBM_SP_REGFILE_SLEEP_CNTL_0,
215357ff00bSCraig Stout 			0x00000441);
216357ff00bSCraig Stout 		gpu_write(gpu, REG_A4XX_RBBM_SP_REGFILE_SLEEP_CNTL_1,
217357ff00bSCraig Stout 			0x00000441);
218357ff00bSCraig Stout 	}
219357ff00bSCraig Stout 
22023bd62fdSAravind Ganesan 	a4xx_enable_hwcg(gpu);
22123bd62fdSAravind Ganesan 
22223bd62fdSAravind Ganesan 	/*
22323bd62fdSAravind Ganesan 	 * For A420 set RBBM_CLOCK_DELAY_HLSQ.CGC_HLSQ_TP_EARLY_CYC >= 2
22423bd62fdSAravind Ganesan 	 * due to timing issue with HLSQ_TP_CLK_EN
22523bd62fdSAravind Ganesan 	 */
22623bd62fdSAravind Ganesan 	if (adreno_is_a420(adreno_gpu)) {
22723bd62fdSAravind Ganesan 		unsigned int val;
22823bd62fdSAravind Ganesan 		val = gpu_read(gpu, REG_A4XX_RBBM_CLOCK_DELAY_HLSQ);
22923bd62fdSAravind Ganesan 		val &= ~A4XX_CGC_HLSQ_EARLY_CYC__MASK;
23023bd62fdSAravind Ganesan 		val |= 2 << A4XX_CGC_HLSQ_EARLY_CYC__SHIFT;
23123bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_HLSQ, val);
23223bd62fdSAravind Ganesan 	}
23323bd62fdSAravind Ganesan 
23423bd62fdSAravind Ganesan 	/* setup access protection: */
23523bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_CP_PROTECT_CTRL, 0x00000007);
23623bd62fdSAravind Ganesan 
23723bd62fdSAravind Ganesan 	/* RBBM registers */
23823bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_CP_PROTECT(0), 0x62000010);
23923bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_CP_PROTECT(1), 0x63000020);
24023bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_CP_PROTECT(2), 0x64000040);
24123bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_CP_PROTECT(3), 0x65000080);
24223bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_CP_PROTECT(4), 0x66000100);
24323bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_CP_PROTECT(5), 0x64000200);
24423bd62fdSAravind Ganesan 
24523bd62fdSAravind Ganesan 	/* CP registers */
24623bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_CP_PROTECT(6), 0x67000800);
24723bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_CP_PROTECT(7), 0x64001600);
24823bd62fdSAravind Ganesan 
24923bd62fdSAravind Ganesan 
25023bd62fdSAravind Ganesan 	/* RB registers */
25123bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_CP_PROTECT(8), 0x60003300);
25223bd62fdSAravind Ganesan 
25323bd62fdSAravind Ganesan 	/* HLSQ registers */
25423bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_CP_PROTECT(9), 0x60003800);
25523bd62fdSAravind Ganesan 
25623bd62fdSAravind Ganesan 	/* VPC registers */
25723bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_CP_PROTECT(10), 0x61003980);
25823bd62fdSAravind Ganesan 
25923bd62fdSAravind Ganesan 	/* SMMU registers */
26023bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_CP_PROTECT(11), 0x6e010000);
26123bd62fdSAravind Ganesan 
26223bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_INT_0_MASK, A4XX_INT0_MASK);
26323bd62fdSAravind Ganesan 
26423bd62fdSAravind Ganesan 	ret = adreno_hw_init(gpu);
26523bd62fdSAravind Ganesan 	if (ret)
26623bd62fdSAravind Ganesan 		return ret;
26723bd62fdSAravind Ganesan 
26823bd62fdSAravind Ganesan 	/* Load PM4: */
269c5e3548cSJordan Crouse 	ptr = (uint32_t *)(adreno_gpu->fw[ADRENO_FW_PM4]->data);
270c5e3548cSJordan Crouse 	len = adreno_gpu->fw[ADRENO_FW_PM4]->size / 4;
27123bd62fdSAravind Ganesan 	DBG("loading PM4 ucode version: %u", ptr[0]);
27223bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_CP_ME_RAM_WADDR, 0);
27323bd62fdSAravind Ganesan 	for (i = 1; i < len; i++)
27423bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_CP_ME_RAM_DATA, ptr[i]);
27523bd62fdSAravind Ganesan 
27623bd62fdSAravind Ganesan 	/* Load PFP: */
277c5e3548cSJordan Crouse 	ptr = (uint32_t *)(adreno_gpu->fw[ADRENO_FW_PFP]->data);
278c5e3548cSJordan Crouse 	len = adreno_gpu->fw[ADRENO_FW_PFP]->size / 4;
27923bd62fdSAravind Ganesan 	DBG("loading PFP ucode version: %u", ptr[0]);
28023bd62fdSAravind Ganesan 
28123bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_CP_PFP_UCODE_ADDR, 0);
28223bd62fdSAravind Ganesan 	for (i = 1; i < len; i++)
28323bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_CP_PFP_UCODE_DATA, ptr[i]);
28423bd62fdSAravind Ganesan 
28523bd62fdSAravind Ganesan 	/* clear ME_HALT to start micro engine */
28623bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_CP_ME_CNTL, 0);
28723bd62fdSAravind Ganesan 
288c4a8d475SJordan Crouse 	return a4xx_me_init(gpu) ? 0 : -EINVAL;
28923bd62fdSAravind Ganesan }
29023bd62fdSAravind Ganesan 
29123bd62fdSAravind Ganesan static void a4xx_recover(struct msm_gpu *gpu)
29223bd62fdSAravind Ganesan {
293398efc46SRob Clark 	int i;
294398efc46SRob Clark 
29526716185SRob Clark 	adreno_dump_info(gpu);
29626716185SRob Clark 
297398efc46SRob Clark 	for (i = 0; i < 8; i++) {
298398efc46SRob Clark 		printk("CP_SCRATCH_REG%d: %u\n", i,
299398efc46SRob Clark 			gpu_read(gpu, REG_AXXX_CP_SCRATCH_REG0 + i));
300398efc46SRob Clark 	}
301398efc46SRob Clark 
30223bd62fdSAravind Ganesan 	/* dump registers before resetting gpu, if enabled: */
30323bd62fdSAravind Ganesan 	if (hang_debug)
30423bd62fdSAravind Ganesan 		a4xx_dump(gpu);
30523bd62fdSAravind Ganesan 
30623bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_SW_RESET_CMD, 1);
30723bd62fdSAravind Ganesan 	gpu_read(gpu, REG_A4XX_RBBM_SW_RESET_CMD);
30823bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_SW_RESET_CMD, 0);
30923bd62fdSAravind Ganesan 	adreno_recover(gpu);
31023bd62fdSAravind Ganesan }
31123bd62fdSAravind Ganesan 
31223bd62fdSAravind Ganesan static void a4xx_destroy(struct msm_gpu *gpu)
31323bd62fdSAravind Ganesan {
31423bd62fdSAravind Ganesan 	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
31523bd62fdSAravind Ganesan 	struct a4xx_gpu *a4xx_gpu = to_a4xx_gpu(adreno_gpu);
31623bd62fdSAravind Ganesan 
31723bd62fdSAravind Ganesan 	DBG("%s", gpu->name);
31823bd62fdSAravind Ganesan 
31923bd62fdSAravind Ganesan 	adreno_gpu_cleanup(adreno_gpu);
32023bd62fdSAravind Ganesan 
32123bd62fdSAravind Ganesan #ifdef CONFIG_MSM_OCMEM
32223bd62fdSAravind Ganesan 	if (a4xx_gpu->ocmem_base)
32323bd62fdSAravind Ganesan 		ocmem_free(OCMEM_GRAPHICS, a4xx_gpu->ocmem_hdl);
32423bd62fdSAravind Ganesan #endif
32523bd62fdSAravind Ganesan 
32623bd62fdSAravind Ganesan 	kfree(a4xx_gpu);
32723bd62fdSAravind Ganesan }
32823bd62fdSAravind Ganesan 
329c4a8d475SJordan Crouse static bool a4xx_idle(struct msm_gpu *gpu)
33023bd62fdSAravind Ganesan {
33123bd62fdSAravind Ganesan 	/* wait for ringbuffer to drain: */
332f97decacSJordan Crouse 	if (!adreno_idle(gpu, gpu->rb[0]))
333c4a8d475SJordan Crouse 		return false;
33423bd62fdSAravind Ganesan 
33523bd62fdSAravind Ganesan 	/* then wait for GPU to finish: */
33623bd62fdSAravind Ganesan 	if (spin_until(!(gpu_read(gpu, REG_A4XX_RBBM_STATUS) &
337c4a8d475SJordan Crouse 					A4XX_RBBM_STATUS_GPU_BUSY))) {
33823bd62fdSAravind Ganesan 		DRM_ERROR("%s: timeout waiting for GPU to idle!\n", gpu->name);
33923bd62fdSAravind Ganesan 		/* TODO maybe we need to reset GPU here to recover from hang? */
340c4a8d475SJordan Crouse 		return false;
341c4a8d475SJordan Crouse 	}
342c4a8d475SJordan Crouse 
343c4a8d475SJordan Crouse 	return true;
34423bd62fdSAravind Ganesan }
34523bd62fdSAravind Ganesan 
34623bd62fdSAravind Ganesan static irqreturn_t a4xx_irq(struct msm_gpu *gpu)
34723bd62fdSAravind Ganesan {
34823bd62fdSAravind Ganesan 	uint32_t status;
34923bd62fdSAravind Ganesan 
35023bd62fdSAravind Ganesan 	status = gpu_read(gpu, REG_A4XX_RBBM_INT_0_STATUS);
35123bd62fdSAravind Ganesan 	DBG("%s: Int status %08x", gpu->name, status);
35223bd62fdSAravind Ganesan 
3531e2c8e7aSCraig Stout 	if (status & A4XX_INT0_CP_REG_PROTECT_FAULT) {
3541e2c8e7aSCraig Stout 		uint32_t reg = gpu_read(gpu, REG_A4XX_CP_PROTECT_STATUS);
3551e2c8e7aSCraig Stout 		printk("CP | Protected mode error| %s | addr=%x\n",
3561e2c8e7aSCraig Stout 			reg & (1 << 24) ? "WRITE" : "READ",
3571e2c8e7aSCraig Stout 			(reg & 0xFFFFF) >> 2);
3581e2c8e7aSCraig Stout 	}
3591e2c8e7aSCraig Stout 
36023bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_INT_CLEAR_CMD, status);
36123bd62fdSAravind Ganesan 
36223bd62fdSAravind Ganesan 	msm_gpu_retire(gpu);
36323bd62fdSAravind Ganesan 
36423bd62fdSAravind Ganesan 	return IRQ_HANDLED;
36523bd62fdSAravind Ganesan }
36623bd62fdSAravind Ganesan 
36723bd62fdSAravind Ganesan static const unsigned int a4xx_registers[] = {
36823bd62fdSAravind Ganesan 	/* RBBM */
36923bd62fdSAravind Ganesan 	0x0000, 0x0002, 0x0004, 0x0021, 0x0023, 0x0024, 0x0026, 0x0026,
37023bd62fdSAravind Ganesan 	0x0028, 0x002B, 0x002E, 0x0034, 0x0037, 0x0044, 0x0047, 0x0066,
37123bd62fdSAravind Ganesan 	0x0068, 0x0095, 0x009C, 0x0170, 0x0174, 0x01AF,
37223bd62fdSAravind Ganesan 	/* CP */
37323bd62fdSAravind Ganesan 	0x0200, 0x0233, 0x0240, 0x0250, 0x04C0, 0x04DD, 0x0500, 0x050B,
37423bd62fdSAravind Ganesan 	0x0578, 0x058F,
37523bd62fdSAravind Ganesan 	/* VSC */
37623bd62fdSAravind Ganesan 	0x0C00, 0x0C03, 0x0C08, 0x0C41, 0x0C50, 0x0C51,
37723bd62fdSAravind Ganesan 	/* GRAS */
37823bd62fdSAravind Ganesan 	0x0C80, 0x0C81, 0x0C88, 0x0C8F,
37923bd62fdSAravind Ganesan 	/* RB */
38023bd62fdSAravind Ganesan 	0x0CC0, 0x0CC0, 0x0CC4, 0x0CD2,
38123bd62fdSAravind Ganesan 	/* PC */
38223bd62fdSAravind Ganesan 	0x0D00, 0x0D0C, 0x0D10, 0x0D17, 0x0D20, 0x0D23,
38323bd62fdSAravind Ganesan 	/* VFD */
38423bd62fdSAravind Ganesan 	0x0E40, 0x0E4A,
38523bd62fdSAravind Ganesan 	/* VPC */
38623bd62fdSAravind Ganesan 	0x0E60, 0x0E61, 0x0E63, 0x0E68,
38723bd62fdSAravind Ganesan 	/* UCHE */
38823bd62fdSAravind Ganesan 	0x0E80, 0x0E84, 0x0E88, 0x0E95,
38923bd62fdSAravind Ganesan 	/* VMIDMT */
39023bd62fdSAravind Ganesan 	0x1000, 0x1000, 0x1002, 0x1002, 0x1004, 0x1004, 0x1008, 0x100A,
39123bd62fdSAravind Ganesan 	0x100C, 0x100D, 0x100F, 0x1010, 0x1012, 0x1016, 0x1024, 0x1024,
39223bd62fdSAravind Ganesan 	0x1027, 0x1027, 0x1100, 0x1100, 0x1102, 0x1102, 0x1104, 0x1104,
39323bd62fdSAravind Ganesan 	0x1110, 0x1110, 0x1112, 0x1116, 0x1124, 0x1124, 0x1300, 0x1300,
39423bd62fdSAravind Ganesan 	0x1380, 0x1380,
39523bd62fdSAravind Ganesan 	/* GRAS CTX 0 */
39623bd62fdSAravind Ganesan 	0x2000, 0x2004, 0x2008, 0x2067, 0x2070, 0x2078, 0x207B, 0x216E,
39723bd62fdSAravind Ganesan 	/* PC CTX 0 */
39823bd62fdSAravind Ganesan 	0x21C0, 0x21C6, 0x21D0, 0x21D0, 0x21D9, 0x21D9, 0x21E5, 0x21E7,
39923bd62fdSAravind Ganesan 	/* VFD CTX 0 */
40023bd62fdSAravind Ganesan 	0x2200, 0x2204, 0x2208, 0x22A9,
40123bd62fdSAravind Ganesan 	/* GRAS CTX 1 */
40223bd62fdSAravind Ganesan 	0x2400, 0x2404, 0x2408, 0x2467, 0x2470, 0x2478, 0x247B, 0x256E,
40323bd62fdSAravind Ganesan 	/* PC CTX 1 */
40423bd62fdSAravind Ganesan 	0x25C0, 0x25C6, 0x25D0, 0x25D0, 0x25D9, 0x25D9, 0x25E5, 0x25E7,
40523bd62fdSAravind Ganesan 	/* VFD CTX 1 */
40623bd62fdSAravind Ganesan 	0x2600, 0x2604, 0x2608, 0x26A9,
40723bd62fdSAravind Ganesan 	/* XPU */
40823bd62fdSAravind Ganesan 	0x2C00, 0x2C01, 0x2C10, 0x2C10, 0x2C12, 0x2C16, 0x2C1D, 0x2C20,
40923bd62fdSAravind Ganesan 	0x2C28, 0x2C28, 0x2C30, 0x2C30, 0x2C32, 0x2C36, 0x2C40, 0x2C40,
41023bd62fdSAravind Ganesan 	0x2C50, 0x2C50, 0x2C52, 0x2C56, 0x2C80, 0x2C80, 0x2C94, 0x2C95,
41123bd62fdSAravind Ganesan 	/* VBIF */
41223bd62fdSAravind Ganesan 	0x3000, 0x3007, 0x300C, 0x3014, 0x3018, 0x301D, 0x3020, 0x3022,
41323bd62fdSAravind Ganesan 	0x3024, 0x3026, 0x3028, 0x302A, 0x302C, 0x302D, 0x3030, 0x3031,
41423bd62fdSAravind Ganesan 	0x3034, 0x3036, 0x3038, 0x3038, 0x303C, 0x303D, 0x3040, 0x3040,
41523bd62fdSAravind Ganesan 	0x3049, 0x3049, 0x3058, 0x3058, 0x305B, 0x3061, 0x3064, 0x3068,
41623bd62fdSAravind Ganesan 	0x306C, 0x306D, 0x3080, 0x3088, 0x308B, 0x308C, 0x3090, 0x3094,
41723bd62fdSAravind Ganesan 	0x3098, 0x3098, 0x309C, 0x309C, 0x30C0, 0x30C0, 0x30C8, 0x30C8,
41823bd62fdSAravind Ganesan 	0x30D0, 0x30D0, 0x30D8, 0x30D8, 0x30E0, 0x30E0, 0x3100, 0x3100,
41923bd62fdSAravind Ganesan 	0x3108, 0x3108, 0x3110, 0x3110, 0x3118, 0x3118, 0x3120, 0x3120,
42023bd62fdSAravind Ganesan 	0x3124, 0x3125, 0x3129, 0x3129, 0x3131, 0x3131, 0x330C, 0x330C,
42123bd62fdSAravind Ganesan 	0x3310, 0x3310, 0x3400, 0x3401, 0x3410, 0x3410, 0x3412, 0x3416,
42223bd62fdSAravind Ganesan 	0x341D, 0x3420, 0x3428, 0x3428, 0x3430, 0x3430, 0x3432, 0x3436,
42323bd62fdSAravind Ganesan 	0x3440, 0x3440, 0x3450, 0x3450, 0x3452, 0x3456, 0x3480, 0x3480,
42423bd62fdSAravind Ganesan 	0x3494, 0x3495, 0x4000, 0x4000, 0x4002, 0x4002, 0x4004, 0x4004,
42523bd62fdSAravind Ganesan 	0x4008, 0x400A, 0x400C, 0x400D, 0x400F, 0x4012, 0x4014, 0x4016,
42623bd62fdSAravind Ganesan 	0x401D, 0x401D, 0x4020, 0x4027, 0x4060, 0x4062, 0x4200, 0x4200,
42723bd62fdSAravind Ganesan 	0x4300, 0x4300, 0x4400, 0x4400, 0x4500, 0x4500, 0x4800, 0x4802,
42823bd62fdSAravind Ganesan 	0x480F, 0x480F, 0x4811, 0x4811, 0x4813, 0x4813, 0x4815, 0x4816,
42923bd62fdSAravind Ganesan 	0x482B, 0x482B, 0x4857, 0x4857, 0x4883, 0x4883, 0x48AF, 0x48AF,
43023bd62fdSAravind Ganesan 	0x48C5, 0x48C5, 0x48E5, 0x48E5, 0x4905, 0x4905, 0x4925, 0x4925,
43123bd62fdSAravind Ganesan 	0x4945, 0x4945, 0x4950, 0x4950, 0x495B, 0x495B, 0x4980, 0x498E,
43223bd62fdSAravind Ganesan 	0x4B00, 0x4B00, 0x4C00, 0x4C00, 0x4D00, 0x4D00, 0x4E00, 0x4E00,
43323bd62fdSAravind Ganesan 	0x4E80, 0x4E80, 0x4F00, 0x4F00, 0x4F08, 0x4F08, 0x4F10, 0x4F10,
43423bd62fdSAravind Ganesan 	0x4F18, 0x4F18, 0x4F20, 0x4F20, 0x4F30, 0x4F30, 0x4F60, 0x4F60,
43523bd62fdSAravind Ganesan 	0x4F80, 0x4F81, 0x4F88, 0x4F89, 0x4FEE, 0x4FEE, 0x4FF3, 0x4FF3,
43623bd62fdSAravind Ganesan 	0x6000, 0x6001, 0x6008, 0x600F, 0x6014, 0x6016, 0x6018, 0x601B,
43723bd62fdSAravind Ganesan 	0x61FD, 0x61FD, 0x623C, 0x623C, 0x6380, 0x6380, 0x63A0, 0x63A0,
43823bd62fdSAravind Ganesan 	0x63C0, 0x63C1, 0x63C8, 0x63C9, 0x63D0, 0x63D4, 0x63D6, 0x63D6,
43923bd62fdSAravind Ganesan 	0x63EE, 0x63EE, 0x6400, 0x6401, 0x6408, 0x640F, 0x6414, 0x6416,
44023bd62fdSAravind Ganesan 	0x6418, 0x641B, 0x65FD, 0x65FD, 0x663C, 0x663C, 0x6780, 0x6780,
44123bd62fdSAravind Ganesan 	0x67A0, 0x67A0, 0x67C0, 0x67C1, 0x67C8, 0x67C9, 0x67D0, 0x67D4,
44223bd62fdSAravind Ganesan 	0x67D6, 0x67D6, 0x67EE, 0x67EE, 0x6800, 0x6801, 0x6808, 0x680F,
44323bd62fdSAravind Ganesan 	0x6814, 0x6816, 0x6818, 0x681B, 0x69FD, 0x69FD, 0x6A3C, 0x6A3C,
44423bd62fdSAravind Ganesan 	0x6B80, 0x6B80, 0x6BA0, 0x6BA0, 0x6BC0, 0x6BC1, 0x6BC8, 0x6BC9,
44523bd62fdSAravind Ganesan 	0x6BD0, 0x6BD4, 0x6BD6, 0x6BD6, 0x6BEE, 0x6BEE,
44623bd62fdSAravind Ganesan 	~0 /* sentinel */
44723bd62fdSAravind Ganesan };
44823bd62fdSAravind Ganesan 
449e00e473dSJordan Crouse static struct msm_gpu_state *a4xx_gpu_state_get(struct msm_gpu *gpu)
450e00e473dSJordan Crouse {
45150f8d218SJordan Crouse 	struct msm_gpu_state *state = kzalloc(sizeof(*state), GFP_KERNEL);
452e00e473dSJordan Crouse 
45350f8d218SJordan Crouse 	if (!state)
45450f8d218SJordan Crouse 		return ERR_PTR(-ENOMEM);
45550f8d218SJordan Crouse 
45650f8d218SJordan Crouse 	adreno_gpu_state_get(gpu, state);
457e00e473dSJordan Crouse 
458e00e473dSJordan Crouse 	state->rbbm_status = gpu_read(gpu, REG_A4XX_RBBM_STATUS);
459e00e473dSJordan Crouse 
460e00e473dSJordan Crouse 	return state;
461e00e473dSJordan Crouse }
462e00e473dSJordan Crouse 
46323bd62fdSAravind Ganesan /* Register offset defines for A4XX, in order of enum adreno_regs */
46423bd62fdSAravind Ganesan static const unsigned int a4xx_register_offsets[REG_ADRENO_REGISTER_MAX] = {
46523bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_BASE, REG_A4XX_CP_RB_BASE),
466fb039981SJordan Crouse 	REG_ADRENO_SKIP(REG_ADRENO_CP_RB_BASE_HI),
46723bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR_ADDR, REG_A4XX_CP_RB_RPTR_ADDR),
468fb039981SJordan Crouse 	REG_ADRENO_SKIP(REG_ADRENO_CP_RB_RPTR_ADDR_HI),
46923bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR, REG_A4XX_CP_RB_RPTR),
47023bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_WPTR, REG_A4XX_CP_RB_WPTR),
47123bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_CNTL, REG_A4XX_CP_RB_CNTL),
47223bd62fdSAravind Ganesan };
47323bd62fdSAravind Ganesan 
47423bd62fdSAravind Ganesan static void a4xx_dump(struct msm_gpu *gpu)
47523bd62fdSAravind Ganesan {
47623bd62fdSAravind Ganesan 	printk("status:   %08x\n",
47723bd62fdSAravind Ganesan 			gpu_read(gpu, REG_A4XX_RBBM_STATUS));
47823bd62fdSAravind Ganesan 	adreno_dump(gpu);
47923bd62fdSAravind Ganesan }
48023bd62fdSAravind Ganesan 
48138bbc55eSCraig Stout static int a4xx_pm_resume(struct msm_gpu *gpu) {
48238bbc55eSCraig Stout 	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
48338bbc55eSCraig Stout 	int ret;
48438bbc55eSCraig Stout 
48538bbc55eSCraig Stout 	ret = msm_gpu_pm_resume(gpu);
48638bbc55eSCraig Stout 	if (ret)
48738bbc55eSCraig Stout 		return ret;
48838bbc55eSCraig Stout 
48938bbc55eSCraig Stout 	if (adreno_is_a430(adreno_gpu)) {
49038bbc55eSCraig Stout 		unsigned int reg;
49138bbc55eSCraig Stout 		/* Set the default register values; set SW_COLLAPSE to 0 */
49238bbc55eSCraig Stout 		gpu_write(gpu, REG_A4XX_RBBM_POWER_CNTL_IP, 0x778000);
49338bbc55eSCraig Stout 		do {
49438bbc55eSCraig Stout 			udelay(5);
49538bbc55eSCraig Stout 			reg = gpu_read(gpu, REG_A4XX_RBBM_POWER_STATUS);
49638bbc55eSCraig Stout 		} while (!(reg & A4XX_RBBM_POWER_CNTL_IP_SP_TP_PWR_ON));
49738bbc55eSCraig Stout 	}
49838bbc55eSCraig Stout 	return 0;
49938bbc55eSCraig Stout }
50038bbc55eSCraig Stout 
50138bbc55eSCraig Stout static int a4xx_pm_suspend(struct msm_gpu *gpu) {
50238bbc55eSCraig Stout 	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
50338bbc55eSCraig Stout 	int ret;
50438bbc55eSCraig Stout 
50538bbc55eSCraig Stout 	ret = msm_gpu_pm_suspend(gpu);
50638bbc55eSCraig Stout 	if (ret)
50738bbc55eSCraig Stout 		return ret;
50838bbc55eSCraig Stout 
50938bbc55eSCraig Stout 	if (adreno_is_a430(adreno_gpu)) {
51038bbc55eSCraig Stout 		/* Set the default register values; set SW_COLLAPSE to 1 */
51138bbc55eSCraig Stout 		gpu_write(gpu, REG_A4XX_RBBM_POWER_CNTL_IP, 0x778001);
51238bbc55eSCraig Stout 	}
51338bbc55eSCraig Stout 	return 0;
51438bbc55eSCraig Stout }
51538bbc55eSCraig Stout 
5166c77d1abSRob Clark static int a4xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value)
5176c77d1abSRob Clark {
518ae53a829SJordan Crouse 	*value = gpu_read64(gpu, REG_A4XX_RBBM_PERFCTR_CP_0_LO,
519ae53a829SJordan Crouse 		REG_A4XX_RBBM_PERFCTR_CP_0_HI);
5206c77d1abSRob Clark 
5216c77d1abSRob Clark 	return 0;
5226c77d1abSRob Clark }
5236c77d1abSRob Clark 
52423bd62fdSAravind Ganesan static const struct adreno_gpu_funcs funcs = {
52523bd62fdSAravind Ganesan 	.base = {
52623bd62fdSAravind Ganesan 		.get_param = adreno_get_param,
52723bd62fdSAravind Ganesan 		.hw_init = a4xx_hw_init,
52838bbc55eSCraig Stout 		.pm_suspend = a4xx_pm_suspend,
52938bbc55eSCraig Stout 		.pm_resume = a4xx_pm_resume,
53023bd62fdSAravind Ganesan 		.recover = a4xx_recover,
53123bd62fdSAravind Ganesan 		.submit = adreno_submit,
53223bd62fdSAravind Ganesan 		.flush = adreno_flush,
533f97decacSJordan Crouse 		.active_ring = adreno_active_ring,
53423bd62fdSAravind Ganesan 		.irq = a4xx_irq,
53523bd62fdSAravind Ganesan 		.destroy = a4xx_destroy,
536c0fec7f5SJordan Crouse #if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP)
5374f776f45SJordan Crouse 		.show = adreno_show,
53823bd62fdSAravind Ganesan #endif
539e00e473dSJordan Crouse 		.gpu_state_get = a4xx_gpu_state_get,
540e00e473dSJordan Crouse 		.gpu_state_put = adreno_gpu_state_put,
54123bd62fdSAravind Ganesan 	},
5426c77d1abSRob Clark 	.get_timestamp = a4xx_get_timestamp,
54323bd62fdSAravind Ganesan };
54423bd62fdSAravind Ganesan 
54523bd62fdSAravind Ganesan struct msm_gpu *a4xx_gpu_init(struct drm_device *dev)
54623bd62fdSAravind Ganesan {
54723bd62fdSAravind Ganesan 	struct a4xx_gpu *a4xx_gpu = NULL;
54823bd62fdSAravind Ganesan 	struct adreno_gpu *adreno_gpu;
54923bd62fdSAravind Ganesan 	struct msm_gpu *gpu;
55023bd62fdSAravind Ganesan 	struct msm_drm_private *priv = dev->dev_private;
55123bd62fdSAravind Ganesan 	struct platform_device *pdev = priv->gpu_pdev;
55223bd62fdSAravind Ganesan 	int ret;
55323bd62fdSAravind Ganesan 
55423bd62fdSAravind Ganesan 	if (!pdev) {
5556a41da17SMamta Shukla 		DRM_DEV_ERROR(dev->dev, "no a4xx device\n");
55623bd62fdSAravind Ganesan 		ret = -ENXIO;
55723bd62fdSAravind Ganesan 		goto fail;
55823bd62fdSAravind Ganesan 	}
55923bd62fdSAravind Ganesan 
56023bd62fdSAravind Ganesan 	a4xx_gpu = kzalloc(sizeof(*a4xx_gpu), GFP_KERNEL);
56123bd62fdSAravind Ganesan 	if (!a4xx_gpu) {
56223bd62fdSAravind Ganesan 		ret = -ENOMEM;
56323bd62fdSAravind Ganesan 		goto fail;
56423bd62fdSAravind Ganesan 	}
56523bd62fdSAravind Ganesan 
56623bd62fdSAravind Ganesan 	adreno_gpu = &a4xx_gpu->base;
56723bd62fdSAravind Ganesan 	gpu = &adreno_gpu->base;
56823bd62fdSAravind Ganesan 
56923bd62fdSAravind Ganesan 	gpu->perfcntrs = NULL;
57023bd62fdSAravind Ganesan 	gpu->num_perfcntrs = 0;
57123bd62fdSAravind Ganesan 
57223bd62fdSAravind Ganesan 	adreno_gpu->registers = a4xx_registers;
57323bd62fdSAravind Ganesan 	adreno_gpu->reg_offsets = a4xx_register_offsets;
57423bd62fdSAravind Ganesan 
575f97decacSJordan Crouse 	ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1);
57623bd62fdSAravind Ganesan 	if (ret)
57723bd62fdSAravind Ganesan 		goto fail;
57823bd62fdSAravind Ganesan 
57923bd62fdSAravind Ganesan 	/* if needed, allocate gmem: */
58023bd62fdSAravind Ganesan 	if (adreno_is_a4xx(adreno_gpu)) {
58123bd62fdSAravind Ganesan #ifdef CONFIG_MSM_OCMEM
58223bd62fdSAravind Ganesan 		/* TODO this is different/missing upstream: */
58323bd62fdSAravind Ganesan 		struct ocmem_buf *ocmem_hdl =
58423bd62fdSAravind Ganesan 				ocmem_allocate(OCMEM_GRAPHICS, adreno_gpu->gmem);
58523bd62fdSAravind Ganesan 
58623bd62fdSAravind Ganesan 		a4xx_gpu->ocmem_hdl = ocmem_hdl;
58723bd62fdSAravind Ganesan 		a4xx_gpu->ocmem_base = ocmem_hdl->addr;
58823bd62fdSAravind Ganesan 		adreno_gpu->gmem = ocmem_hdl->len;
58923bd62fdSAravind Ganesan 		DBG("using %dK of OCMEM at 0x%08x", adreno_gpu->gmem / 1024,
59023bd62fdSAravind Ganesan 				a4xx_gpu->ocmem_base);
59123bd62fdSAravind Ganesan #endif
59223bd62fdSAravind Ganesan 	}
59323bd62fdSAravind Ganesan 
594667ce33eSRob Clark 	if (!gpu->aspace) {
59523bd62fdSAravind Ganesan 		/* TODO we think it is possible to configure the GPU to
59623bd62fdSAravind Ganesan 		 * restrict access to VRAM carveout.  But the required
59723bd62fdSAravind Ganesan 		 * registers are unknown.  For now just bail out and
59823bd62fdSAravind Ganesan 		 * limp along with just modesetting.  If it turns out
59923bd62fdSAravind Ganesan 		 * to not be possible to restrict access, then we must
60023bd62fdSAravind Ganesan 		 * implement a cmdstream validator.
60123bd62fdSAravind Ganesan 		 */
6026a41da17SMamta Shukla 		DRM_DEV_ERROR(dev->dev, "No memory protection without IOMMU\n");
60323bd62fdSAravind Ganesan 		ret = -ENXIO;
60423bd62fdSAravind Ganesan 		goto fail;
60523bd62fdSAravind Ganesan 	}
60623bd62fdSAravind Ganesan 
60723bd62fdSAravind Ganesan 	return gpu;
60823bd62fdSAravind Ganesan 
60923bd62fdSAravind Ganesan fail:
61023bd62fdSAravind Ganesan 	if (a4xx_gpu)
61123bd62fdSAravind Ganesan 		a4xx_destroy(&a4xx_gpu->base.base);
61223bd62fdSAravind Ganesan 
61323bd62fdSAravind Ganesan 	return ERR_PTR(ret);
61423bd62fdSAravind Ganesan }
615