xref: /linux/drivers/gpu/drm/msm/adreno/a4xx_gpu.c (revision 398efc46f80f312ef6414bc366ae141945869028)
123bd62fdSAravind Ganesan /* Copyright (c) 2014 The Linux Foundation. All rights reserved.
223bd62fdSAravind Ganesan  *
323bd62fdSAravind Ganesan  * This program is free software; you can redistribute it and/or modify
423bd62fdSAravind Ganesan  * it under the terms of the GNU General Public License version 2 and
523bd62fdSAravind Ganesan  * only version 2 as published by the Free Software Foundation.
623bd62fdSAravind Ganesan  *
723bd62fdSAravind Ganesan  * This program is distributed in the hope that it will be useful,
823bd62fdSAravind Ganesan  * but WITHOUT ANY WARRANTY; without even the implied warranty of
923bd62fdSAravind Ganesan  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1023bd62fdSAravind Ganesan  * GNU General Public License for more details.
1123bd62fdSAravind Ganesan  *
1223bd62fdSAravind Ganesan  */
1323bd62fdSAravind Ganesan #include "a4xx_gpu.h"
1423bd62fdSAravind Ganesan #ifdef CONFIG_MSM_OCMEM
1523bd62fdSAravind Ganesan #  include <soc/qcom/ocmem.h>
1623bd62fdSAravind Ganesan #endif
1723bd62fdSAravind Ganesan 
1823bd62fdSAravind Ganesan #define A4XX_INT0_MASK \
1923bd62fdSAravind Ganesan 	(A4XX_INT0_RBBM_AHB_ERROR |        \
2023bd62fdSAravind Ganesan 	 A4XX_INT0_RBBM_ATB_BUS_OVERFLOW | \
2123bd62fdSAravind Ganesan 	 A4XX_INT0_CP_T0_PACKET_IN_IB |    \
2223bd62fdSAravind Ganesan 	 A4XX_INT0_CP_OPCODE_ERROR |       \
2323bd62fdSAravind Ganesan 	 A4XX_INT0_CP_RESERVED_BIT_ERROR | \
2423bd62fdSAravind Ganesan 	 A4XX_INT0_CP_HW_FAULT |           \
2523bd62fdSAravind Ganesan 	 A4XX_INT0_CP_IB1_INT |            \
2623bd62fdSAravind Ganesan 	 A4XX_INT0_CP_IB2_INT |            \
2723bd62fdSAravind Ganesan 	 A4XX_INT0_CP_RB_INT |             \
2823bd62fdSAravind Ganesan 	 A4XX_INT0_CP_REG_PROTECT_FAULT |  \
2923bd62fdSAravind Ganesan 	 A4XX_INT0_CP_AHB_ERROR_HALT |     \
3023bd62fdSAravind Ganesan 	 A4XX_INT0_UCHE_OOB_ACCESS)
3123bd62fdSAravind Ganesan 
3223bd62fdSAravind Ganesan extern bool hang_debug;
3323bd62fdSAravind Ganesan static void a4xx_dump(struct msm_gpu *gpu);
3423bd62fdSAravind Ganesan 
3523bd62fdSAravind Ganesan /*
3623bd62fdSAravind Ganesan  * a4xx_enable_hwcg() - Program the clock control registers
3723bd62fdSAravind Ganesan  * @device: The adreno device pointer
3823bd62fdSAravind Ganesan  */
3923bd62fdSAravind Ganesan static void a4xx_enable_hwcg(struct msm_gpu *gpu)
4023bd62fdSAravind Ganesan {
4123bd62fdSAravind Ganesan 	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
4223bd62fdSAravind Ganesan 	unsigned int i;
4323bd62fdSAravind Ganesan 	for (i = 0; i < 4; i++)
4423bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_TP(i), 0x02222202);
4523bd62fdSAravind Ganesan 	for (i = 0; i < 4; i++)
4623bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL2_TP(i), 0x00002222);
4723bd62fdSAravind Ganesan 	for (i = 0; i < 4; i++)
4823bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_TP(i), 0x0E739CE7);
4923bd62fdSAravind Ganesan 	for (i = 0; i < 4; i++)
5023bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_TP(i), 0x00111111);
5123bd62fdSAravind Ganesan 	for (i = 0; i < 4; i++)
5223bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_SP(i), 0x22222222);
5323bd62fdSAravind Ganesan 	for (i = 0; i < 4; i++)
5423bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL2_SP(i), 0x00222222);
5523bd62fdSAravind Ganesan 	for (i = 0; i < 4; i++)
5623bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_SP(i), 0x00000104);
5723bd62fdSAravind Ganesan 	for (i = 0; i < 4; i++)
5823bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_SP(i), 0x00000081);
5923bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_UCHE, 0x22222222);
6023bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL2_UCHE, 0x02222222);
6123bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL3_UCHE, 0x00000000);
6223bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL4_UCHE, 0x00000000);
6323bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_UCHE, 0x00004444);
6423bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_UCHE, 0x00001112);
6523bd62fdSAravind Ganesan 	for (i = 0; i < 4; i++)
6623bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_RB(i), 0x22222222);
6723bd62fdSAravind Ganesan 
6823bd62fdSAravind Ganesan 	/* Disable L1 clocking in A420 due to CCU issues with it */
6923bd62fdSAravind Ganesan 	for (i = 0; i < 4; i++) {
7023bd62fdSAravind Ganesan 		if (adreno_is_a420(adreno_gpu)) {
7123bd62fdSAravind Ganesan 			gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL2_RB(i),
7223bd62fdSAravind Ganesan 					0x00002020);
7323bd62fdSAravind Ganesan 		} else {
7423bd62fdSAravind Ganesan 			gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL2_RB(i),
7523bd62fdSAravind Ganesan 					0x00022020);
7623bd62fdSAravind Ganesan 		}
7723bd62fdSAravind Ganesan 	}
7823bd62fdSAravind Ganesan 
7923bd62fdSAravind Ganesan 	for (i = 0; i < 4; i++) {
8023bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_MARB_CCU(i),
8123bd62fdSAravind Ganesan 				0x00000922);
8223bd62fdSAravind Ganesan 	}
8323bd62fdSAravind Ganesan 
8423bd62fdSAravind Ganesan 	for (i = 0; i < 4; i++) {
8523bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_RB_MARB_CCU(i),
8623bd62fdSAravind Ganesan 				0x00000000);
8723bd62fdSAravind Ganesan 	}
8823bd62fdSAravind Ganesan 
8923bd62fdSAravind Ganesan 	for (i = 0; i < 4; i++) {
9023bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_RB_MARB_CCU_L1(i),
9123bd62fdSAravind Ganesan 				0x00000001);
9223bd62fdSAravind Ganesan 	}
9323bd62fdSAravind Ganesan 
9423bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_CLOCK_MODE_GPC, 0x02222222);
9523bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_GPC, 0x04100104);
9623bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_GPC, 0x00022222);
9723bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_COM_DCOM, 0x00000022);
9823bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_COM_DCOM, 0x0000010F);
9923bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_COM_DCOM, 0x00000022);
10023bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_TSE_RAS_RBBM, 0x00222222);
10123bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00004104);
10223bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00000222);
10323bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_HLSQ , 0x00000000);
10423bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_HLSQ, 0x00000000);
105357ff00bSCraig Stout 	gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_HLSQ, 0x00220000);
106357ff00bSCraig Stout 	/* Early A430's have a timing issue with SP/TP power collapse;
107357ff00bSCraig Stout 	   disabling HW clock gating prevents it. */
108357ff00bSCraig Stout 	if (adreno_is_a430(adreno_gpu) && adreno_gpu->rev.patchid < 2)
109357ff00bSCraig Stout 		gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL, 0);
110357ff00bSCraig Stout 	else
11123bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL, 0xAAAAAAAA);
11223bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL2, 0);
11323bd62fdSAravind Ganesan }
11423bd62fdSAravind Ganesan 
115357ff00bSCraig Stout 
11623bd62fdSAravind Ganesan static void a4xx_me_init(struct msm_gpu *gpu)
11723bd62fdSAravind Ganesan {
11823bd62fdSAravind Ganesan 	struct msm_ringbuffer *ring = gpu->rb;
11923bd62fdSAravind Ganesan 
12023bd62fdSAravind Ganesan 	OUT_PKT3(ring, CP_ME_INIT, 17);
12123bd62fdSAravind Ganesan 	OUT_RING(ring, 0x000003f7);
12223bd62fdSAravind Ganesan 	OUT_RING(ring, 0x00000000);
12323bd62fdSAravind Ganesan 	OUT_RING(ring, 0x00000000);
12423bd62fdSAravind Ganesan 	OUT_RING(ring, 0x00000000);
12523bd62fdSAravind Ganesan 	OUT_RING(ring, 0x00000080);
12623bd62fdSAravind Ganesan 	OUT_RING(ring, 0x00000100);
12723bd62fdSAravind Ganesan 	OUT_RING(ring, 0x00000180);
12823bd62fdSAravind Ganesan 	OUT_RING(ring, 0x00006600);
12923bd62fdSAravind Ganesan 	OUT_RING(ring, 0x00000150);
13023bd62fdSAravind Ganesan 	OUT_RING(ring, 0x0000014e);
13123bd62fdSAravind Ganesan 	OUT_RING(ring, 0x00000154);
13223bd62fdSAravind Ganesan 	OUT_RING(ring, 0x00000001);
13323bd62fdSAravind Ganesan 	OUT_RING(ring, 0x00000000);
13423bd62fdSAravind Ganesan 	OUT_RING(ring, 0x00000000);
13523bd62fdSAravind Ganesan 	OUT_RING(ring, 0x00000000);
13623bd62fdSAravind Ganesan 	OUT_RING(ring, 0x00000000);
13723bd62fdSAravind Ganesan 	OUT_RING(ring, 0x00000000);
13823bd62fdSAravind Ganesan 
13923bd62fdSAravind Ganesan 	gpu->funcs->flush(gpu);
14023bd62fdSAravind Ganesan 	gpu->funcs->idle(gpu);
14123bd62fdSAravind Ganesan }
14223bd62fdSAravind Ganesan 
14323bd62fdSAravind Ganesan static int a4xx_hw_init(struct msm_gpu *gpu)
14423bd62fdSAravind Ganesan {
14523bd62fdSAravind Ganesan 	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
14623bd62fdSAravind Ganesan 	struct a4xx_gpu *a4xx_gpu = to_a4xx_gpu(adreno_gpu);
14723bd62fdSAravind Ganesan 	uint32_t *ptr, len;
14823bd62fdSAravind Ganesan 	int i, ret;
14923bd62fdSAravind Ganesan 
150357ff00bSCraig Stout 	if (adreno_is_a420(adreno_gpu)) {
15123bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_VBIF_ABIT_SORT, 0x0001001F);
15223bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_VBIF_ABIT_SORT_CONF, 0x000000A4);
15323bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_VBIF_GATE_OFF_WRREQ_EN, 0x00000001);
15423bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_VBIF_IN_RD_LIM_CONF0, 0x18181818);
15523bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_VBIF_IN_RD_LIM_CONF1, 0x00000018);
15623bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_VBIF_IN_WR_LIM_CONF0, 0x18181818);
15723bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_VBIF_IN_WR_LIM_CONF1, 0x00000018);
15823bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x00000003);
159357ff00bSCraig Stout 	} else if (adreno_is_a430(adreno_gpu)) {
160357ff00bSCraig Stout 		gpu_write(gpu, REG_A4XX_VBIF_GATE_OFF_WRREQ_EN, 0x00000001);
161357ff00bSCraig Stout 		gpu_write(gpu, REG_A4XX_VBIF_IN_RD_LIM_CONF0, 0x18181818);
162357ff00bSCraig Stout 		gpu_write(gpu, REG_A4XX_VBIF_IN_RD_LIM_CONF1, 0x00000018);
163357ff00bSCraig Stout 		gpu_write(gpu, REG_A4XX_VBIF_IN_WR_LIM_CONF0, 0x18181818);
164357ff00bSCraig Stout 		gpu_write(gpu, REG_A4XX_VBIF_IN_WR_LIM_CONF1, 0x00000018);
165357ff00bSCraig Stout 		gpu_write(gpu, REG_A4XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x00000003);
16623bd62fdSAravind Ganesan 	} else {
16723bd62fdSAravind Ganesan 		BUG();
16823bd62fdSAravind Ganesan 	}
16923bd62fdSAravind Ganesan 
17023bd62fdSAravind Ganesan 	/* Make all blocks contribute to the GPU BUSY perf counter */
17123bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_GPU_BUSY_MASKED, 0xffffffff);
17223bd62fdSAravind Ganesan 
17323bd62fdSAravind Ganesan 	/* Tune the hystersis counters for SP and CP idle detection */
17423bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_SP_HYST_CNT, 0x10);
17523bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_WAIT_IDLE_CLOCKS_CTL, 0x10);
17623bd62fdSAravind Ganesan 
177357ff00bSCraig Stout 	if (adreno_is_a430(adreno_gpu)) {
178357ff00bSCraig Stout 		gpu_write(gpu, REG_A4XX_RBBM_WAIT_IDLE_CLOCKS_CTL2, 0x30);
179357ff00bSCraig Stout 	}
180357ff00bSCraig Stout 
18123bd62fdSAravind Ganesan 	 /* Enable the RBBM error reporting bits */
18223bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_AHB_CTL0, 0x00000001);
18323bd62fdSAravind Ganesan 
18423bd62fdSAravind Ganesan 	/* Enable AHB error reporting*/
18523bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_AHB_CTL1, 0xa6ffffff);
18623bd62fdSAravind Ganesan 
18723bd62fdSAravind Ganesan 	/* Enable power counters*/
18823bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_RBBM_CTL, 0x00000030);
18923bd62fdSAravind Ganesan 
19023bd62fdSAravind Ganesan 	/*
19123bd62fdSAravind Ganesan 	 * Turn on hang detection - this spews a lot of useful information
19223bd62fdSAravind Ganesan 	 * into the RBBM registers on a hang:
19323bd62fdSAravind Ganesan 	 */
19423bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_INTERFACE_HANG_INT_CTL,
19523bd62fdSAravind Ganesan 			(1 << 30) | 0xFFFF);
19623bd62fdSAravind Ganesan 
19723bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RB_GMEM_BASE_ADDR,
19823bd62fdSAravind Ganesan 			(unsigned int)(a4xx_gpu->ocmem_base >> 14));
19923bd62fdSAravind Ganesan 
20023bd62fdSAravind Ganesan 	/* Turn on performance counters: */
20123bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_PERFCTR_CTL, 0x01);
20223bd62fdSAravind Ganesan 
2036c77d1abSRob Clark 	/* use the first CP counter for timestamp queries.. userspace may set
2046c77d1abSRob Clark 	 * this as well but it selects the same counter/countable:
2056c77d1abSRob Clark 	 */
2066c77d1abSRob Clark 	gpu_write(gpu, REG_A4XX_CP_PERFCTR_CP_SEL_0, CP_ALWAYS_COUNT);
2076c77d1abSRob Clark 
208357ff00bSCraig Stout 	if (adreno_is_a430(adreno_gpu))
209357ff00bSCraig Stout 		gpu_write(gpu, REG_A4XX_UCHE_CACHE_WAYS_VFD, 0x07);
210357ff00bSCraig Stout 
21123bd62fdSAravind Ganesan 	/* Disable L2 bypass to avoid UCHE out of bounds errors */
21223bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_UCHE_TRAP_BASE_LO, 0xffff0000);
21323bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_UCHE_TRAP_BASE_HI, 0xffff0000);
21423bd62fdSAravind Ganesan 
21523bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_CP_DEBUG, (1 << 25) |
21623bd62fdSAravind Ganesan 			(adreno_is_a420(adreno_gpu) ? (1 << 29) : 0));
21723bd62fdSAravind Ganesan 
218357ff00bSCraig Stout 	/* On A430 enable SP regfile sleep for power savings */
219357ff00bSCraig Stout 	/* TODO downstream does this for !420, so maybe applies for 405 too? */
220357ff00bSCraig Stout 	if (!adreno_is_a420(adreno_gpu)) {
221357ff00bSCraig Stout 		gpu_write(gpu, REG_A4XX_RBBM_SP_REGFILE_SLEEP_CNTL_0,
222357ff00bSCraig Stout 			0x00000441);
223357ff00bSCraig Stout 		gpu_write(gpu, REG_A4XX_RBBM_SP_REGFILE_SLEEP_CNTL_1,
224357ff00bSCraig Stout 			0x00000441);
225357ff00bSCraig Stout 	}
226357ff00bSCraig Stout 
22723bd62fdSAravind Ganesan 	a4xx_enable_hwcg(gpu);
22823bd62fdSAravind Ganesan 
22923bd62fdSAravind Ganesan 	/*
23023bd62fdSAravind Ganesan 	 * For A420 set RBBM_CLOCK_DELAY_HLSQ.CGC_HLSQ_TP_EARLY_CYC >= 2
23123bd62fdSAravind Ganesan 	 * due to timing issue with HLSQ_TP_CLK_EN
23223bd62fdSAravind Ganesan 	 */
23323bd62fdSAravind Ganesan 	if (adreno_is_a420(adreno_gpu)) {
23423bd62fdSAravind Ganesan 		unsigned int val;
23523bd62fdSAravind Ganesan 		val = gpu_read(gpu, REG_A4XX_RBBM_CLOCK_DELAY_HLSQ);
23623bd62fdSAravind Ganesan 		val &= ~A4XX_CGC_HLSQ_EARLY_CYC__MASK;
23723bd62fdSAravind Ganesan 		val |= 2 << A4XX_CGC_HLSQ_EARLY_CYC__SHIFT;
23823bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_HLSQ, val);
23923bd62fdSAravind Ganesan 	}
24023bd62fdSAravind Ganesan 
24123bd62fdSAravind Ganesan 	/* setup access protection: */
24223bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_CP_PROTECT_CTRL, 0x00000007);
24323bd62fdSAravind Ganesan 
24423bd62fdSAravind Ganesan 	/* RBBM registers */
24523bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_CP_PROTECT(0), 0x62000010);
24623bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_CP_PROTECT(1), 0x63000020);
24723bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_CP_PROTECT(2), 0x64000040);
24823bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_CP_PROTECT(3), 0x65000080);
24923bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_CP_PROTECT(4), 0x66000100);
25023bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_CP_PROTECT(5), 0x64000200);
25123bd62fdSAravind Ganesan 
25223bd62fdSAravind Ganesan 	/* CP registers */
25323bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_CP_PROTECT(6), 0x67000800);
25423bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_CP_PROTECT(7), 0x64001600);
25523bd62fdSAravind Ganesan 
25623bd62fdSAravind Ganesan 
25723bd62fdSAravind Ganesan 	/* RB registers */
25823bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_CP_PROTECT(8), 0x60003300);
25923bd62fdSAravind Ganesan 
26023bd62fdSAravind Ganesan 	/* HLSQ registers */
26123bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_CP_PROTECT(9), 0x60003800);
26223bd62fdSAravind Ganesan 
26323bd62fdSAravind Ganesan 	/* VPC registers */
26423bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_CP_PROTECT(10), 0x61003980);
26523bd62fdSAravind Ganesan 
26623bd62fdSAravind Ganesan 	/* SMMU registers */
26723bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_CP_PROTECT(11), 0x6e010000);
26823bd62fdSAravind Ganesan 
26923bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_INT_0_MASK, A4XX_INT0_MASK);
27023bd62fdSAravind Ganesan 
27123bd62fdSAravind Ganesan 	ret = adreno_hw_init(gpu);
27223bd62fdSAravind Ganesan 	if (ret)
27323bd62fdSAravind Ganesan 		return ret;
27423bd62fdSAravind Ganesan 
27523bd62fdSAravind Ganesan 	/* Load PM4: */
27623bd62fdSAravind Ganesan 	ptr = (uint32_t *)(adreno_gpu->pm4->data);
27723bd62fdSAravind Ganesan 	len = adreno_gpu->pm4->size / 4;
27823bd62fdSAravind Ganesan 	DBG("loading PM4 ucode version: %u", ptr[0]);
27923bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_CP_ME_RAM_WADDR, 0);
28023bd62fdSAravind Ganesan 	for (i = 1; i < len; i++)
28123bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_CP_ME_RAM_DATA, ptr[i]);
28223bd62fdSAravind Ganesan 
28323bd62fdSAravind Ganesan 	/* Load PFP: */
28423bd62fdSAravind Ganesan 	ptr = (uint32_t *)(adreno_gpu->pfp->data);
28523bd62fdSAravind Ganesan 	len = adreno_gpu->pfp->size / 4;
28623bd62fdSAravind Ganesan 	DBG("loading PFP ucode version: %u", ptr[0]);
28723bd62fdSAravind Ganesan 
28823bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_CP_PFP_UCODE_ADDR, 0);
28923bd62fdSAravind Ganesan 	for (i = 1; i < len; i++)
29023bd62fdSAravind Ganesan 		gpu_write(gpu, REG_A4XX_CP_PFP_UCODE_DATA, ptr[i]);
29123bd62fdSAravind Ganesan 
29223bd62fdSAravind Ganesan 	/* clear ME_HALT to start micro engine */
29323bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_CP_ME_CNTL, 0);
29423bd62fdSAravind Ganesan 
29523bd62fdSAravind Ganesan 	a4xx_me_init(gpu);
2966c77d1abSRob Clark 
29723bd62fdSAravind Ganesan 	return 0;
29823bd62fdSAravind Ganesan }
29923bd62fdSAravind Ganesan 
30023bd62fdSAravind Ganesan static void a4xx_recover(struct msm_gpu *gpu)
30123bd62fdSAravind Ganesan {
302*398efc46SRob Clark 	int i;
303*398efc46SRob Clark 
30426716185SRob Clark 	adreno_dump_info(gpu);
30526716185SRob Clark 
306*398efc46SRob Clark 	for (i = 0; i < 8; i++) {
307*398efc46SRob Clark 		printk("CP_SCRATCH_REG%d: %u\n", i,
308*398efc46SRob Clark 			gpu_read(gpu, REG_AXXX_CP_SCRATCH_REG0 + i));
309*398efc46SRob Clark 	}
310*398efc46SRob Clark 
31123bd62fdSAravind Ganesan 	/* dump registers before resetting gpu, if enabled: */
31223bd62fdSAravind Ganesan 	if (hang_debug)
31323bd62fdSAravind Ganesan 		a4xx_dump(gpu);
31423bd62fdSAravind Ganesan 
31523bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_SW_RESET_CMD, 1);
31623bd62fdSAravind Ganesan 	gpu_read(gpu, REG_A4XX_RBBM_SW_RESET_CMD);
31723bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_SW_RESET_CMD, 0);
31823bd62fdSAravind Ganesan 	adreno_recover(gpu);
31923bd62fdSAravind Ganesan }
32023bd62fdSAravind Ganesan 
32123bd62fdSAravind Ganesan static void a4xx_destroy(struct msm_gpu *gpu)
32223bd62fdSAravind Ganesan {
32323bd62fdSAravind Ganesan 	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
32423bd62fdSAravind Ganesan 	struct a4xx_gpu *a4xx_gpu = to_a4xx_gpu(adreno_gpu);
32523bd62fdSAravind Ganesan 
32623bd62fdSAravind Ganesan 	DBG("%s", gpu->name);
32723bd62fdSAravind Ganesan 
32823bd62fdSAravind Ganesan 	adreno_gpu_cleanup(adreno_gpu);
32923bd62fdSAravind Ganesan 
33023bd62fdSAravind Ganesan #ifdef CONFIG_MSM_OCMEM
33123bd62fdSAravind Ganesan 	if (a4xx_gpu->ocmem_base)
33223bd62fdSAravind Ganesan 		ocmem_free(OCMEM_GRAPHICS, a4xx_gpu->ocmem_hdl);
33323bd62fdSAravind Ganesan #endif
33423bd62fdSAravind Ganesan 
33523bd62fdSAravind Ganesan 	kfree(a4xx_gpu);
33623bd62fdSAravind Ganesan }
33723bd62fdSAravind Ganesan 
33823bd62fdSAravind Ganesan static void a4xx_idle(struct msm_gpu *gpu)
33923bd62fdSAravind Ganesan {
34023bd62fdSAravind Ganesan 	/* wait for ringbuffer to drain: */
34123bd62fdSAravind Ganesan 	adreno_idle(gpu);
34223bd62fdSAravind Ganesan 
34323bd62fdSAravind Ganesan 	/* then wait for GPU to finish: */
34423bd62fdSAravind Ganesan 	if (spin_until(!(gpu_read(gpu, REG_A4XX_RBBM_STATUS) &
34523bd62fdSAravind Ganesan 					A4XX_RBBM_STATUS_GPU_BUSY)))
34623bd62fdSAravind Ganesan 		DRM_ERROR("%s: timeout waiting for GPU to idle!\n", gpu->name);
34723bd62fdSAravind Ganesan 
34823bd62fdSAravind Ganesan 	/* TODO maybe we need to reset GPU here to recover from hang? */
34923bd62fdSAravind Ganesan }
35023bd62fdSAravind Ganesan 
35123bd62fdSAravind Ganesan static irqreturn_t a4xx_irq(struct msm_gpu *gpu)
35223bd62fdSAravind Ganesan {
35323bd62fdSAravind Ganesan 	uint32_t status;
35423bd62fdSAravind Ganesan 
35523bd62fdSAravind Ganesan 	status = gpu_read(gpu, REG_A4XX_RBBM_INT_0_STATUS);
35623bd62fdSAravind Ganesan 	DBG("%s: Int status %08x", gpu->name, status);
35723bd62fdSAravind Ganesan 
3581e2c8e7aSCraig Stout 	if (status & A4XX_INT0_CP_REG_PROTECT_FAULT) {
3591e2c8e7aSCraig Stout 		uint32_t reg = gpu_read(gpu, REG_A4XX_CP_PROTECT_STATUS);
3601e2c8e7aSCraig Stout 		printk("CP | Protected mode error| %s | addr=%x\n",
3611e2c8e7aSCraig Stout 			reg & (1 << 24) ? "WRITE" : "READ",
3621e2c8e7aSCraig Stout 			(reg & 0xFFFFF) >> 2);
3631e2c8e7aSCraig Stout 	}
3641e2c8e7aSCraig Stout 
36523bd62fdSAravind Ganesan 	gpu_write(gpu, REG_A4XX_RBBM_INT_CLEAR_CMD, status);
36623bd62fdSAravind Ganesan 
36723bd62fdSAravind Ganesan 	msm_gpu_retire(gpu);
36823bd62fdSAravind Ganesan 
36923bd62fdSAravind Ganesan 	return IRQ_HANDLED;
37023bd62fdSAravind Ganesan }
37123bd62fdSAravind Ganesan 
37223bd62fdSAravind Ganesan static const unsigned int a4xx_registers[] = {
37323bd62fdSAravind Ganesan 	/* RBBM */
37423bd62fdSAravind Ganesan 	0x0000, 0x0002, 0x0004, 0x0021, 0x0023, 0x0024, 0x0026, 0x0026,
37523bd62fdSAravind Ganesan 	0x0028, 0x002B, 0x002E, 0x0034, 0x0037, 0x0044, 0x0047, 0x0066,
37623bd62fdSAravind Ganesan 	0x0068, 0x0095, 0x009C, 0x0170, 0x0174, 0x01AF,
37723bd62fdSAravind Ganesan 	/* CP */
37823bd62fdSAravind Ganesan 	0x0200, 0x0233, 0x0240, 0x0250, 0x04C0, 0x04DD, 0x0500, 0x050B,
37923bd62fdSAravind Ganesan 	0x0578, 0x058F,
38023bd62fdSAravind Ganesan 	/* VSC */
38123bd62fdSAravind Ganesan 	0x0C00, 0x0C03, 0x0C08, 0x0C41, 0x0C50, 0x0C51,
38223bd62fdSAravind Ganesan 	/* GRAS */
38323bd62fdSAravind Ganesan 	0x0C80, 0x0C81, 0x0C88, 0x0C8F,
38423bd62fdSAravind Ganesan 	/* RB */
38523bd62fdSAravind Ganesan 	0x0CC0, 0x0CC0, 0x0CC4, 0x0CD2,
38623bd62fdSAravind Ganesan 	/* PC */
38723bd62fdSAravind Ganesan 	0x0D00, 0x0D0C, 0x0D10, 0x0D17, 0x0D20, 0x0D23,
38823bd62fdSAravind Ganesan 	/* VFD */
38923bd62fdSAravind Ganesan 	0x0E40, 0x0E4A,
39023bd62fdSAravind Ganesan 	/* VPC */
39123bd62fdSAravind Ganesan 	0x0E60, 0x0E61, 0x0E63, 0x0E68,
39223bd62fdSAravind Ganesan 	/* UCHE */
39323bd62fdSAravind Ganesan 	0x0E80, 0x0E84, 0x0E88, 0x0E95,
39423bd62fdSAravind Ganesan 	/* VMIDMT */
39523bd62fdSAravind Ganesan 	0x1000, 0x1000, 0x1002, 0x1002, 0x1004, 0x1004, 0x1008, 0x100A,
39623bd62fdSAravind Ganesan 	0x100C, 0x100D, 0x100F, 0x1010, 0x1012, 0x1016, 0x1024, 0x1024,
39723bd62fdSAravind Ganesan 	0x1027, 0x1027, 0x1100, 0x1100, 0x1102, 0x1102, 0x1104, 0x1104,
39823bd62fdSAravind Ganesan 	0x1110, 0x1110, 0x1112, 0x1116, 0x1124, 0x1124, 0x1300, 0x1300,
39923bd62fdSAravind Ganesan 	0x1380, 0x1380,
40023bd62fdSAravind Ganesan 	/* GRAS CTX 0 */
40123bd62fdSAravind Ganesan 	0x2000, 0x2004, 0x2008, 0x2067, 0x2070, 0x2078, 0x207B, 0x216E,
40223bd62fdSAravind Ganesan 	/* PC CTX 0 */
40323bd62fdSAravind Ganesan 	0x21C0, 0x21C6, 0x21D0, 0x21D0, 0x21D9, 0x21D9, 0x21E5, 0x21E7,
40423bd62fdSAravind Ganesan 	/* VFD CTX 0 */
40523bd62fdSAravind Ganesan 	0x2200, 0x2204, 0x2208, 0x22A9,
40623bd62fdSAravind Ganesan 	/* GRAS CTX 1 */
40723bd62fdSAravind Ganesan 	0x2400, 0x2404, 0x2408, 0x2467, 0x2470, 0x2478, 0x247B, 0x256E,
40823bd62fdSAravind Ganesan 	/* PC CTX 1 */
40923bd62fdSAravind Ganesan 	0x25C0, 0x25C6, 0x25D0, 0x25D0, 0x25D9, 0x25D9, 0x25E5, 0x25E7,
41023bd62fdSAravind Ganesan 	/* VFD CTX 1 */
41123bd62fdSAravind Ganesan 	0x2600, 0x2604, 0x2608, 0x26A9,
41223bd62fdSAravind Ganesan 	/* XPU */
41323bd62fdSAravind Ganesan 	0x2C00, 0x2C01, 0x2C10, 0x2C10, 0x2C12, 0x2C16, 0x2C1D, 0x2C20,
41423bd62fdSAravind Ganesan 	0x2C28, 0x2C28, 0x2C30, 0x2C30, 0x2C32, 0x2C36, 0x2C40, 0x2C40,
41523bd62fdSAravind Ganesan 	0x2C50, 0x2C50, 0x2C52, 0x2C56, 0x2C80, 0x2C80, 0x2C94, 0x2C95,
41623bd62fdSAravind Ganesan 	/* VBIF */
41723bd62fdSAravind Ganesan 	0x3000, 0x3007, 0x300C, 0x3014, 0x3018, 0x301D, 0x3020, 0x3022,
41823bd62fdSAravind Ganesan 	0x3024, 0x3026, 0x3028, 0x302A, 0x302C, 0x302D, 0x3030, 0x3031,
41923bd62fdSAravind Ganesan 	0x3034, 0x3036, 0x3038, 0x3038, 0x303C, 0x303D, 0x3040, 0x3040,
42023bd62fdSAravind Ganesan 	0x3049, 0x3049, 0x3058, 0x3058, 0x305B, 0x3061, 0x3064, 0x3068,
42123bd62fdSAravind Ganesan 	0x306C, 0x306D, 0x3080, 0x3088, 0x308B, 0x308C, 0x3090, 0x3094,
42223bd62fdSAravind Ganesan 	0x3098, 0x3098, 0x309C, 0x309C, 0x30C0, 0x30C0, 0x30C8, 0x30C8,
42323bd62fdSAravind Ganesan 	0x30D0, 0x30D0, 0x30D8, 0x30D8, 0x30E0, 0x30E0, 0x3100, 0x3100,
42423bd62fdSAravind Ganesan 	0x3108, 0x3108, 0x3110, 0x3110, 0x3118, 0x3118, 0x3120, 0x3120,
42523bd62fdSAravind Ganesan 	0x3124, 0x3125, 0x3129, 0x3129, 0x3131, 0x3131, 0x330C, 0x330C,
42623bd62fdSAravind Ganesan 	0x3310, 0x3310, 0x3400, 0x3401, 0x3410, 0x3410, 0x3412, 0x3416,
42723bd62fdSAravind Ganesan 	0x341D, 0x3420, 0x3428, 0x3428, 0x3430, 0x3430, 0x3432, 0x3436,
42823bd62fdSAravind Ganesan 	0x3440, 0x3440, 0x3450, 0x3450, 0x3452, 0x3456, 0x3480, 0x3480,
42923bd62fdSAravind Ganesan 	0x3494, 0x3495, 0x4000, 0x4000, 0x4002, 0x4002, 0x4004, 0x4004,
43023bd62fdSAravind Ganesan 	0x4008, 0x400A, 0x400C, 0x400D, 0x400F, 0x4012, 0x4014, 0x4016,
43123bd62fdSAravind Ganesan 	0x401D, 0x401D, 0x4020, 0x4027, 0x4060, 0x4062, 0x4200, 0x4200,
43223bd62fdSAravind Ganesan 	0x4300, 0x4300, 0x4400, 0x4400, 0x4500, 0x4500, 0x4800, 0x4802,
43323bd62fdSAravind Ganesan 	0x480F, 0x480F, 0x4811, 0x4811, 0x4813, 0x4813, 0x4815, 0x4816,
43423bd62fdSAravind Ganesan 	0x482B, 0x482B, 0x4857, 0x4857, 0x4883, 0x4883, 0x48AF, 0x48AF,
43523bd62fdSAravind Ganesan 	0x48C5, 0x48C5, 0x48E5, 0x48E5, 0x4905, 0x4905, 0x4925, 0x4925,
43623bd62fdSAravind Ganesan 	0x4945, 0x4945, 0x4950, 0x4950, 0x495B, 0x495B, 0x4980, 0x498E,
43723bd62fdSAravind Ganesan 	0x4B00, 0x4B00, 0x4C00, 0x4C00, 0x4D00, 0x4D00, 0x4E00, 0x4E00,
43823bd62fdSAravind Ganesan 	0x4E80, 0x4E80, 0x4F00, 0x4F00, 0x4F08, 0x4F08, 0x4F10, 0x4F10,
43923bd62fdSAravind Ganesan 	0x4F18, 0x4F18, 0x4F20, 0x4F20, 0x4F30, 0x4F30, 0x4F60, 0x4F60,
44023bd62fdSAravind Ganesan 	0x4F80, 0x4F81, 0x4F88, 0x4F89, 0x4FEE, 0x4FEE, 0x4FF3, 0x4FF3,
44123bd62fdSAravind Ganesan 	0x6000, 0x6001, 0x6008, 0x600F, 0x6014, 0x6016, 0x6018, 0x601B,
44223bd62fdSAravind Ganesan 	0x61FD, 0x61FD, 0x623C, 0x623C, 0x6380, 0x6380, 0x63A0, 0x63A0,
44323bd62fdSAravind Ganesan 	0x63C0, 0x63C1, 0x63C8, 0x63C9, 0x63D0, 0x63D4, 0x63D6, 0x63D6,
44423bd62fdSAravind Ganesan 	0x63EE, 0x63EE, 0x6400, 0x6401, 0x6408, 0x640F, 0x6414, 0x6416,
44523bd62fdSAravind Ganesan 	0x6418, 0x641B, 0x65FD, 0x65FD, 0x663C, 0x663C, 0x6780, 0x6780,
44623bd62fdSAravind Ganesan 	0x67A0, 0x67A0, 0x67C0, 0x67C1, 0x67C8, 0x67C9, 0x67D0, 0x67D4,
44723bd62fdSAravind Ganesan 	0x67D6, 0x67D6, 0x67EE, 0x67EE, 0x6800, 0x6801, 0x6808, 0x680F,
44823bd62fdSAravind Ganesan 	0x6814, 0x6816, 0x6818, 0x681B, 0x69FD, 0x69FD, 0x6A3C, 0x6A3C,
44923bd62fdSAravind Ganesan 	0x6B80, 0x6B80, 0x6BA0, 0x6BA0, 0x6BC0, 0x6BC1, 0x6BC8, 0x6BC9,
45023bd62fdSAravind Ganesan 	0x6BD0, 0x6BD4, 0x6BD6, 0x6BD6, 0x6BEE, 0x6BEE,
45123bd62fdSAravind Ganesan 	~0 /* sentinel */
45223bd62fdSAravind Ganesan };
45323bd62fdSAravind Ganesan 
45423bd62fdSAravind Ganesan #ifdef CONFIG_DEBUG_FS
45523bd62fdSAravind Ganesan static void a4xx_show(struct msm_gpu *gpu, struct seq_file *m)
45623bd62fdSAravind Ganesan {
45723bd62fdSAravind Ganesan 	gpu->funcs->pm_resume(gpu);
45823bd62fdSAravind Ganesan 
45923bd62fdSAravind Ganesan 	seq_printf(m, "status:   %08x\n",
46023bd62fdSAravind Ganesan 			gpu_read(gpu, REG_A4XX_RBBM_STATUS));
46123bd62fdSAravind Ganesan 	gpu->funcs->pm_suspend(gpu);
46223bd62fdSAravind Ganesan 
46323bd62fdSAravind Ganesan 	adreno_show(gpu, m);
46423bd62fdSAravind Ganesan 
46523bd62fdSAravind Ganesan }
46623bd62fdSAravind Ganesan #endif
46723bd62fdSAravind Ganesan 
46823bd62fdSAravind Ganesan /* Register offset defines for A4XX, in order of enum adreno_regs */
46923bd62fdSAravind Ganesan static const unsigned int a4xx_register_offsets[REG_ADRENO_REGISTER_MAX] = {
47023bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_CP_DEBUG, REG_A4XX_CP_DEBUG),
47123bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_CP_ME_RAM_WADDR, REG_A4XX_CP_ME_RAM_WADDR),
47223bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_CP_ME_RAM_DATA, REG_A4XX_CP_ME_RAM_DATA),
47323bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_CP_PFP_UCODE_DATA,
47423bd62fdSAravind Ganesan 			REG_A4XX_CP_PFP_UCODE_DATA),
47523bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_CP_PFP_UCODE_ADDR,
47623bd62fdSAravind Ganesan 			REG_A4XX_CP_PFP_UCODE_ADDR),
47723bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_CP_WFI_PEND_CTR, REG_A4XX_CP_WFI_PEND_CTR),
47823bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_BASE, REG_A4XX_CP_RB_BASE),
47923bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR_ADDR, REG_A4XX_CP_RB_RPTR_ADDR),
48023bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR, REG_A4XX_CP_RB_RPTR),
48123bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_WPTR, REG_A4XX_CP_RB_WPTR),
48223bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_CP_PROTECT_CTRL, REG_A4XX_CP_PROTECT_CTRL),
48323bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_CP_ME_CNTL, REG_A4XX_CP_ME_CNTL),
48423bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_CNTL, REG_A4XX_CP_RB_CNTL),
48523bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_CP_IB1_BASE, REG_A4XX_CP_IB1_BASE),
48623bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_CP_IB1_BUFSZ, REG_A4XX_CP_IB1_BUFSZ),
48723bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_CP_IB2_BASE, REG_A4XX_CP_IB2_BASE),
48823bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_CP_IB2_BUFSZ, REG_A4XX_CP_IB2_BUFSZ),
48923bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_CP_TIMESTAMP, REG_AXXX_CP_SCRATCH_REG0),
49023bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_CP_ME_RAM_RADDR, REG_A4XX_CP_ME_RAM_RADDR),
49123bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_CP_ROQ_ADDR, REG_A4XX_CP_ROQ_ADDR),
49223bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_CP_ROQ_DATA, REG_A4XX_CP_ROQ_DATA),
49323bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_CP_MERCIU_ADDR, REG_A4XX_CP_MERCIU_ADDR),
49423bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_CP_MERCIU_DATA, REG_A4XX_CP_MERCIU_DATA),
49523bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_CP_MERCIU_DATA2, REG_A4XX_CP_MERCIU_DATA2),
49623bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_CP_MEQ_ADDR, REG_A4XX_CP_MEQ_ADDR),
49723bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_CP_MEQ_DATA, REG_A4XX_CP_MEQ_DATA),
49823bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_CP_HW_FAULT, REG_A4XX_CP_HW_FAULT),
49923bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_CP_PROTECT_STATUS,
50023bd62fdSAravind Ganesan 			REG_A4XX_CP_PROTECT_STATUS),
50123bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_SCRATCH_ADDR, REG_A4XX_CP_SCRATCH_ADDR),
50223bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_SCRATCH_UMSK, REG_A4XX_CP_SCRATCH_UMASK),
50323bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_STATUS, REG_A4XX_RBBM_STATUS),
50423bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_PERFCTR_CTL,
50523bd62fdSAravind Ganesan 			REG_A4XX_RBBM_PERFCTR_CTL),
50623bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_PERFCTR_LOAD_CMD0,
50723bd62fdSAravind Ganesan 			REG_A4XX_RBBM_PERFCTR_LOAD_CMD0),
50823bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_PERFCTR_LOAD_CMD1,
50923bd62fdSAravind Ganesan 			REG_A4XX_RBBM_PERFCTR_LOAD_CMD1),
51023bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_PERFCTR_LOAD_CMD2,
51123bd62fdSAravind Ganesan 			REG_A4XX_RBBM_PERFCTR_LOAD_CMD2),
51223bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_PERFCTR_PWR_1_LO,
51323bd62fdSAravind Ganesan 			REG_A4XX_RBBM_PERFCTR_PWR_1_LO),
51423bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_INT_0_MASK, REG_A4XX_RBBM_INT_0_MASK),
51523bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_INT_0_STATUS,
51623bd62fdSAravind Ganesan 			REG_A4XX_RBBM_INT_0_STATUS),
51723bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_AHB_ERROR_STATUS,
51823bd62fdSAravind Ganesan 			REG_A4XX_RBBM_AHB_ERROR_STATUS),
51923bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_AHB_CMD, REG_A4XX_RBBM_AHB_CMD),
52023bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_CLOCK_CTL, REG_A4XX_RBBM_CLOCK_CTL),
52123bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_AHB_ME_SPLIT_STATUS,
52223bd62fdSAravind Ganesan 			REG_A4XX_RBBM_AHB_ME_SPLIT_STATUS),
52323bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_AHB_PFP_SPLIT_STATUS,
52423bd62fdSAravind Ganesan 			REG_A4XX_RBBM_AHB_PFP_SPLIT_STATUS),
52523bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_VPC_DEBUG_RAM_SEL,
52623bd62fdSAravind Ganesan 			REG_A4XX_VPC_DEBUG_RAM_SEL),
52723bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_VPC_DEBUG_RAM_READ,
52823bd62fdSAravind Ganesan 			REG_A4XX_VPC_DEBUG_RAM_READ),
52923bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_INT_CLEAR_CMD,
53023bd62fdSAravind Ganesan 			REG_A4XX_RBBM_INT_CLEAR_CMD),
53123bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_VSC_SIZE_ADDRESS,
53223bd62fdSAravind Ganesan 			REG_A4XX_VSC_SIZE_ADDRESS),
53323bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_VFD_CONTROL_0, REG_A4XX_VFD_CONTROL_0),
53423bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_SP_VS_PVT_MEM_ADDR_REG,
53523bd62fdSAravind Ganesan 			REG_A4XX_SP_VS_PVT_MEM_ADDR),
53623bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_SP_FS_PVT_MEM_ADDR_REG,
53723bd62fdSAravind Ganesan 			REG_A4XX_SP_FS_PVT_MEM_ADDR),
53823bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_SP_VS_OBJ_START_REG,
53923bd62fdSAravind Ganesan 			REG_A4XX_SP_VS_OBJ_START),
54023bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_SP_FS_OBJ_START_REG,
54123bd62fdSAravind Ganesan 			REG_A4XX_SP_FS_OBJ_START),
54223bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_RBBM_CTL, REG_A4XX_RBBM_RBBM_CTL),
54323bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_SW_RESET_CMD,
54423bd62fdSAravind Ganesan 			REG_A4XX_RBBM_SW_RESET_CMD),
54523bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_UCHE_INVALIDATE0,
54623bd62fdSAravind Ganesan 			REG_A4XX_UCHE_INVALIDATE0),
54723bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_PERFCTR_LOAD_VALUE_LO,
54823bd62fdSAravind Ganesan 			REG_A4XX_RBBM_PERFCTR_LOAD_VALUE_LO),
54923bd62fdSAravind Ganesan 	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_PERFCTR_LOAD_VALUE_HI,
55023bd62fdSAravind Ganesan 			REG_A4XX_RBBM_PERFCTR_LOAD_VALUE_HI),
55123bd62fdSAravind Ganesan };
55223bd62fdSAravind Ganesan 
55323bd62fdSAravind Ganesan static void a4xx_dump(struct msm_gpu *gpu)
55423bd62fdSAravind Ganesan {
55523bd62fdSAravind Ganesan 	printk("status:   %08x\n",
55623bd62fdSAravind Ganesan 			gpu_read(gpu, REG_A4XX_RBBM_STATUS));
55723bd62fdSAravind Ganesan 	adreno_dump(gpu);
55823bd62fdSAravind Ganesan }
55923bd62fdSAravind Ganesan 
56038bbc55eSCraig Stout static int a4xx_pm_resume(struct msm_gpu *gpu) {
56138bbc55eSCraig Stout 	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
56238bbc55eSCraig Stout 	int ret;
56338bbc55eSCraig Stout 
56438bbc55eSCraig Stout 	ret = msm_gpu_pm_resume(gpu);
56538bbc55eSCraig Stout 	if (ret)
56638bbc55eSCraig Stout 		return ret;
56738bbc55eSCraig Stout 
56838bbc55eSCraig Stout 	if (adreno_is_a430(adreno_gpu)) {
56938bbc55eSCraig Stout 		unsigned int reg;
57038bbc55eSCraig Stout 		/* Set the default register values; set SW_COLLAPSE to 0 */
57138bbc55eSCraig Stout 		gpu_write(gpu, REG_A4XX_RBBM_POWER_CNTL_IP, 0x778000);
57238bbc55eSCraig Stout 		do {
57338bbc55eSCraig Stout 			udelay(5);
57438bbc55eSCraig Stout 			reg = gpu_read(gpu, REG_A4XX_RBBM_POWER_STATUS);
57538bbc55eSCraig Stout 		} while (!(reg & A4XX_RBBM_POWER_CNTL_IP_SP_TP_PWR_ON));
57638bbc55eSCraig Stout 	}
57738bbc55eSCraig Stout 	return 0;
57838bbc55eSCraig Stout }
57938bbc55eSCraig Stout 
58038bbc55eSCraig Stout static int a4xx_pm_suspend(struct msm_gpu *gpu) {
58138bbc55eSCraig Stout 	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
58238bbc55eSCraig Stout 	int ret;
58338bbc55eSCraig Stout 
58438bbc55eSCraig Stout 	ret = msm_gpu_pm_suspend(gpu);
58538bbc55eSCraig Stout 	if (ret)
58638bbc55eSCraig Stout 		return ret;
58738bbc55eSCraig Stout 
58838bbc55eSCraig Stout 	if (adreno_is_a430(adreno_gpu)) {
58938bbc55eSCraig Stout 		/* Set the default register values; set SW_COLLAPSE to 1 */
59038bbc55eSCraig Stout 		gpu_write(gpu, REG_A4XX_RBBM_POWER_CNTL_IP, 0x778001);
59138bbc55eSCraig Stout 	}
59238bbc55eSCraig Stout 	return 0;
59338bbc55eSCraig Stout }
59438bbc55eSCraig Stout 
5956c77d1abSRob Clark static int a4xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value)
5966c77d1abSRob Clark {
5976c77d1abSRob Clark 	uint32_t hi, lo, tmp;
5986c77d1abSRob Clark 
5996c77d1abSRob Clark 	tmp = gpu_read(gpu, REG_A4XX_RBBM_PERFCTR_CP_0_HI);
6006c77d1abSRob Clark 	do {
6016c77d1abSRob Clark 		hi = tmp;
6026c77d1abSRob Clark 		lo = gpu_read(gpu, REG_A4XX_RBBM_PERFCTR_CP_0_LO);
6036c77d1abSRob Clark 		tmp = gpu_read(gpu, REG_A4XX_RBBM_PERFCTR_CP_0_HI);
6046c77d1abSRob Clark 	} while (tmp != hi);
6056c77d1abSRob Clark 
6066c77d1abSRob Clark 	*value = (((uint64_t)hi) << 32) | lo;
6076c77d1abSRob Clark 
6086c77d1abSRob Clark 	return 0;
6096c77d1abSRob Clark }
6106c77d1abSRob Clark 
61123bd62fdSAravind Ganesan static const struct adreno_gpu_funcs funcs = {
61223bd62fdSAravind Ganesan 	.base = {
61323bd62fdSAravind Ganesan 		.get_param = adreno_get_param,
61423bd62fdSAravind Ganesan 		.hw_init = a4xx_hw_init,
61538bbc55eSCraig Stout 		.pm_suspend = a4xx_pm_suspend,
61638bbc55eSCraig Stout 		.pm_resume = a4xx_pm_resume,
61723bd62fdSAravind Ganesan 		.recover = a4xx_recover,
61823bd62fdSAravind Ganesan 		.last_fence = adreno_last_fence,
61923bd62fdSAravind Ganesan 		.submit = adreno_submit,
62023bd62fdSAravind Ganesan 		.flush = adreno_flush,
62123bd62fdSAravind Ganesan 		.idle = a4xx_idle,
62223bd62fdSAravind Ganesan 		.irq = a4xx_irq,
62323bd62fdSAravind Ganesan 		.destroy = a4xx_destroy,
62423bd62fdSAravind Ganesan #ifdef CONFIG_DEBUG_FS
62523bd62fdSAravind Ganesan 		.show = a4xx_show,
62623bd62fdSAravind Ganesan #endif
62723bd62fdSAravind Ganesan 	},
6286c77d1abSRob Clark 	.get_timestamp = a4xx_get_timestamp,
62923bd62fdSAravind Ganesan };
63023bd62fdSAravind Ganesan 
63123bd62fdSAravind Ganesan struct msm_gpu *a4xx_gpu_init(struct drm_device *dev)
63223bd62fdSAravind Ganesan {
63323bd62fdSAravind Ganesan 	struct a4xx_gpu *a4xx_gpu = NULL;
63423bd62fdSAravind Ganesan 	struct adreno_gpu *adreno_gpu;
63523bd62fdSAravind Ganesan 	struct msm_gpu *gpu;
63623bd62fdSAravind Ganesan 	struct msm_drm_private *priv = dev->dev_private;
63723bd62fdSAravind Ganesan 	struct platform_device *pdev = priv->gpu_pdev;
63823bd62fdSAravind Ganesan 	int ret;
63923bd62fdSAravind Ganesan 
64023bd62fdSAravind Ganesan 	if (!pdev) {
64123bd62fdSAravind Ganesan 		dev_err(dev->dev, "no a4xx device\n");
64223bd62fdSAravind Ganesan 		ret = -ENXIO;
64323bd62fdSAravind Ganesan 		goto fail;
64423bd62fdSAravind Ganesan 	}
64523bd62fdSAravind Ganesan 
64623bd62fdSAravind Ganesan 	a4xx_gpu = kzalloc(sizeof(*a4xx_gpu), GFP_KERNEL);
64723bd62fdSAravind Ganesan 	if (!a4xx_gpu) {
64823bd62fdSAravind Ganesan 		ret = -ENOMEM;
64923bd62fdSAravind Ganesan 		goto fail;
65023bd62fdSAravind Ganesan 	}
65123bd62fdSAravind Ganesan 
65223bd62fdSAravind Ganesan 	adreno_gpu = &a4xx_gpu->base;
65323bd62fdSAravind Ganesan 	gpu = &adreno_gpu->base;
65423bd62fdSAravind Ganesan 
65523bd62fdSAravind Ganesan 	a4xx_gpu->pdev = pdev;
65623bd62fdSAravind Ganesan 
65723bd62fdSAravind Ganesan 	gpu->perfcntrs = NULL;
65823bd62fdSAravind Ganesan 	gpu->num_perfcntrs = 0;
65923bd62fdSAravind Ganesan 
66023bd62fdSAravind Ganesan 	adreno_gpu->registers = a4xx_registers;
66123bd62fdSAravind Ganesan 	adreno_gpu->reg_offsets = a4xx_register_offsets;
66223bd62fdSAravind Ganesan 
66323bd62fdSAravind Ganesan 	ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs);
66423bd62fdSAravind Ganesan 	if (ret)
66523bd62fdSAravind Ganesan 		goto fail;
66623bd62fdSAravind Ganesan 
66723bd62fdSAravind Ganesan 	/* if needed, allocate gmem: */
66823bd62fdSAravind Ganesan 	if (adreno_is_a4xx(adreno_gpu)) {
66923bd62fdSAravind Ganesan #ifdef CONFIG_MSM_OCMEM
67023bd62fdSAravind Ganesan 		/* TODO this is different/missing upstream: */
67123bd62fdSAravind Ganesan 		struct ocmem_buf *ocmem_hdl =
67223bd62fdSAravind Ganesan 				ocmem_allocate(OCMEM_GRAPHICS, adreno_gpu->gmem);
67323bd62fdSAravind Ganesan 
67423bd62fdSAravind Ganesan 		a4xx_gpu->ocmem_hdl = ocmem_hdl;
67523bd62fdSAravind Ganesan 		a4xx_gpu->ocmem_base = ocmem_hdl->addr;
67623bd62fdSAravind Ganesan 		adreno_gpu->gmem = ocmem_hdl->len;
67723bd62fdSAravind Ganesan 		DBG("using %dK of OCMEM at 0x%08x", adreno_gpu->gmem / 1024,
67823bd62fdSAravind Ganesan 				a4xx_gpu->ocmem_base);
67923bd62fdSAravind Ganesan #endif
68023bd62fdSAravind Ganesan 	}
68123bd62fdSAravind Ganesan 
682667ce33eSRob Clark 	if (!gpu->aspace) {
68323bd62fdSAravind Ganesan 		/* TODO we think it is possible to configure the GPU to
68423bd62fdSAravind Ganesan 		 * restrict access to VRAM carveout.  But the required
68523bd62fdSAravind Ganesan 		 * registers are unknown.  For now just bail out and
68623bd62fdSAravind Ganesan 		 * limp along with just modesetting.  If it turns out
68723bd62fdSAravind Ganesan 		 * to not be possible to restrict access, then we must
68823bd62fdSAravind Ganesan 		 * implement a cmdstream validator.
68923bd62fdSAravind Ganesan 		 */
69023bd62fdSAravind Ganesan 		dev_err(dev->dev, "No memory protection without IOMMU\n");
69123bd62fdSAravind Ganesan 		ret = -ENXIO;
69223bd62fdSAravind Ganesan 		goto fail;
69323bd62fdSAravind Ganesan 	}
69423bd62fdSAravind Ganesan 
69523bd62fdSAravind Ganesan 	return gpu;
69623bd62fdSAravind Ganesan 
69723bd62fdSAravind Ganesan fail:
69823bd62fdSAravind Ganesan 	if (a4xx_gpu)
69923bd62fdSAravind Ganesan 		a4xx_destroy(&a4xx_gpu->base.base);
70023bd62fdSAravind Ganesan 
70123bd62fdSAravind Ganesan 	return ERR_PTR(ret);
70223bd62fdSAravind Ganesan }
703