xref: /linux/drivers/gpu/drm/msm/adreno/a3xx_gpu.c (revision 3a2c4d55e32ad65efebdb6de44eef3bfa08bb49d)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2013 Red Hat
4  * Author: Rob Clark <robdclark@gmail.com>
5  *
6  * Copyright (c) 2014 The Linux Foundation. All rights reserved.
7  */
8 
9 #include "a3xx_gpu.h"
10 
11 #define A3XX_INT0_MASK \
12 	(A3XX_INT0_RBBM_AHB_ERROR |        \
13 	 A3XX_INT0_RBBM_ATB_BUS_OVERFLOW | \
14 	 A3XX_INT0_CP_T0_PACKET_IN_IB |    \
15 	 A3XX_INT0_CP_OPCODE_ERROR |       \
16 	 A3XX_INT0_CP_RESERVED_BIT_ERROR | \
17 	 A3XX_INT0_CP_HW_FAULT |           \
18 	 A3XX_INT0_CP_IB1_INT |            \
19 	 A3XX_INT0_CP_IB2_INT |            \
20 	 A3XX_INT0_CP_RB_INT |             \
21 	 A3XX_INT0_CP_REG_PROTECT_FAULT |  \
22 	 A3XX_INT0_CP_AHB_ERROR_HALT |     \
23 	 A3XX_INT0_CACHE_FLUSH_TS |        \
24 	 A3XX_INT0_UCHE_OOB_ACCESS)
25 
26 extern bool hang_debug;
27 
28 #define A3XX_VBIF_XIN_HALT_CTRL0_MASK	GENMASK(5, 0)
29 
30 static void a3xx_dump(struct msm_gpu *gpu);
31 static bool a3xx_idle(struct msm_gpu *gpu);
32 
33 static void a3xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
34 {
35 	struct msm_ringbuffer *ring = submit->ring;
36 	unsigned int i;
37 
38 	for (i = 0; i < submit->nr_cmds; i++) {
39 		switch (submit->cmd[i].type) {
40 		case MSM_SUBMIT_CMD_IB_TARGET_BUF:
41 			/* ignore IB-targets */
42 			break;
43 		case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
44 			/* ignore if there has not been a ctx switch: */
45 			if (ring->cur_ctx_seqno == submit->queue->ctx->seqno)
46 				break;
47 			fallthrough;
48 		case MSM_SUBMIT_CMD_BUF:
49 			OUT_PKT3(ring, CP_INDIRECT_BUFFER_PFD, 2);
50 			OUT_RING(ring, lower_32_bits(submit->cmd[i].iova));
51 			OUT_RING(ring, submit->cmd[i].size);
52 			OUT_PKT2(ring);
53 			break;
54 		}
55 	}
56 
57 	OUT_PKT0(ring, REG_AXXX_CP_SCRATCH_REG2, 1);
58 	OUT_RING(ring, submit->seqno);
59 
60 	/* Flush HLSQ lazy updates to make sure there is nothing
61 	 * pending for indirect loads after the timestamp has
62 	 * passed:
63 	 */
64 	OUT_PKT3(ring, CP_EVENT_WRITE, 1);
65 	OUT_RING(ring, HLSQ_FLUSH);
66 
67 	/* wait for idle before cache flush/interrupt */
68 	OUT_PKT3(ring, CP_WAIT_FOR_IDLE, 1);
69 	OUT_RING(ring, 0x00000000);
70 
71 	/* BIT(31) of CACHE_FLUSH_TS triggers CACHE_FLUSH_TS IRQ from GPU */
72 	OUT_PKT3(ring, CP_EVENT_WRITE, 3);
73 	OUT_RING(ring, CACHE_FLUSH_TS | CP_EVENT_WRITE_0_IRQ);
74 	OUT_RING(ring, rbmemptr(ring, fence));
75 	OUT_RING(ring, submit->seqno);
76 
77 #if 0
78 	/* Dummy set-constant to trigger context rollover */
79 	OUT_PKT3(ring, CP_SET_CONSTANT, 2);
80 	OUT_RING(ring, CP_REG(REG_A3XX_HLSQ_CL_KERNEL_GROUP_X_REG));
81 	OUT_RING(ring, 0x00000000);
82 #endif
83 
84 	adreno_flush(gpu, ring, REG_AXXX_CP_RB_WPTR);
85 }
86 
87 static bool a3xx_me_init(struct msm_gpu *gpu)
88 {
89 	struct msm_ringbuffer *ring = gpu->rb[0];
90 
91 	OUT_PKT3(ring, CP_ME_INIT, 17);
92 	OUT_RING(ring, 0x000003f7);
93 	OUT_RING(ring, 0x00000000);
94 	OUT_RING(ring, 0x00000000);
95 	OUT_RING(ring, 0x00000000);
96 	OUT_RING(ring, 0x00000080);
97 	OUT_RING(ring, 0x00000100);
98 	OUT_RING(ring, 0x00000180);
99 	OUT_RING(ring, 0x00006600);
100 	OUT_RING(ring, 0x00000150);
101 	OUT_RING(ring, 0x0000014e);
102 	OUT_RING(ring, 0x00000154);
103 	OUT_RING(ring, 0x00000001);
104 	OUT_RING(ring, 0x00000000);
105 	OUT_RING(ring, 0x00000000);
106 	OUT_RING(ring, 0x00000000);
107 	OUT_RING(ring, 0x00000000);
108 	OUT_RING(ring, 0x00000000);
109 
110 	adreno_flush(gpu, ring, REG_AXXX_CP_RB_WPTR);
111 	return a3xx_idle(gpu);
112 }
113 
114 static int a3xx_hw_init(struct msm_gpu *gpu)
115 {
116 	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
117 	struct a3xx_gpu *a3xx_gpu = to_a3xx_gpu(adreno_gpu);
118 	uint32_t *ptr, len;
119 	int i, ret;
120 
121 	DBG("%s", gpu->name);
122 
123 	if (adreno_is_a305(adreno_gpu)) {
124 		/* Set up 16 deep read/write request queues: */
125 		gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF0, 0x10101010);
126 		gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF1, 0x10101010);
127 		gpu_write(gpu, REG_A3XX_VBIF_OUT_RD_LIM_CONF0, 0x10101010);
128 		gpu_write(gpu, REG_A3XX_VBIF_OUT_WR_LIM_CONF0, 0x10101010);
129 		gpu_write(gpu, REG_A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303);
130 		gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF0, 0x10101010);
131 		gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF1, 0x10101010);
132 		/* Enable WR-REQ: */
133 		gpu_write(gpu, REG_A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x0000ff);
134 		/* Set up round robin arbitration between both AXI ports: */
135 		gpu_write(gpu, REG_A3XX_VBIF_ARB_CTL, 0x00000030);
136 		/* Set up AOOO: */
137 		gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000003c);
138 		gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO, 0x003c003c);
139 	} else if (adreno_is_a305b(adreno_gpu)) {
140 		gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF0, 0x00181818);
141 		gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF0, 0x00181818);
142 		gpu_write(gpu, REG_A3XX_VBIF_OUT_RD_LIM_CONF0, 0x00000018);
143 		gpu_write(gpu, REG_A3XX_VBIF_OUT_WR_LIM_CONF0, 0x00000018);
144 		gpu_write(gpu, REG_A3XX_VBIF_DDR_OUT_MAX_BURST, 0x00000303);
145 		gpu_write(gpu, REG_A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0003);
146 	} else if (adreno_is_a306(adreno_gpu)) {
147 		gpu_write(gpu, REG_A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0003);
148 		gpu_write(gpu, REG_A3XX_VBIF_OUT_RD_LIM_CONF0, 0x0000000a);
149 		gpu_write(gpu, REG_A3XX_VBIF_OUT_WR_LIM_CONF0, 0x0000000a);
150 	} else if (adreno_is_a306a(adreno_gpu)) {
151 		gpu_write(gpu, REG_A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0003);
152 		gpu_write(gpu, REG_A3XX_VBIF_OUT_RD_LIM_CONF0, 0x00000010);
153 		gpu_write(gpu, REG_A3XX_VBIF_OUT_WR_LIM_CONF0, 0x00000010);
154 	} else if (adreno_is_a320(adreno_gpu)) {
155 		/* Set up 16 deep read/write request queues: */
156 		gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF0, 0x10101010);
157 		gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF1, 0x10101010);
158 		gpu_write(gpu, REG_A3XX_VBIF_OUT_RD_LIM_CONF0, 0x10101010);
159 		gpu_write(gpu, REG_A3XX_VBIF_OUT_WR_LIM_CONF0, 0x10101010);
160 		gpu_write(gpu, REG_A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303);
161 		gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF0, 0x10101010);
162 		gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF1, 0x10101010);
163 		/* Enable WR-REQ: */
164 		gpu_write(gpu, REG_A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x0000ff);
165 		/* Set up round robin arbitration between both AXI ports: */
166 		gpu_write(gpu, REG_A3XX_VBIF_ARB_CTL, 0x00000030);
167 		/* Set up AOOO: */
168 		gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000003c);
169 		gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO, 0x003c003c);
170 		/* Enable 1K sort: */
171 		gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT, 0x000000ff);
172 		gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT_CONF, 0x000000a4);
173 
174 	} else if (adreno_is_a330v2(adreno_gpu)) {
175 		/*
176 		 * Most of the VBIF registers on 8974v2 have the correct
177 		 * values at power on, so we won't modify those if we don't
178 		 * need to
179 		 */
180 		/* Enable 1k sort: */
181 		gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT, 0x0001003f);
182 		gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT_CONF, 0x000000a4);
183 		/* Enable WR-REQ: */
184 		gpu_write(gpu, REG_A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x00003f);
185 		gpu_write(gpu, REG_A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303);
186 		/* Set up VBIF_ROUND_ROBIN_QOS_ARB: */
187 		gpu_write(gpu, REG_A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0003);
188 
189 	} else if (adreno_is_a330(adreno_gpu)) {
190 		/* Set up 16 deep read/write request queues: */
191 		gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF0, 0x18181818);
192 		gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF1, 0x18181818);
193 		gpu_write(gpu, REG_A3XX_VBIF_OUT_RD_LIM_CONF0, 0x18181818);
194 		gpu_write(gpu, REG_A3XX_VBIF_OUT_WR_LIM_CONF0, 0x18181818);
195 		gpu_write(gpu, REG_A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303);
196 		gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF0, 0x18181818);
197 		gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF1, 0x18181818);
198 		/* Enable WR-REQ: */
199 		gpu_write(gpu, REG_A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x00003f);
200 		/* Set up round robin arbitration between both AXI ports: */
201 		gpu_write(gpu, REG_A3XX_VBIF_ARB_CTL, 0x00000030);
202 		/* Set up VBIF_ROUND_ROBIN_QOS_ARB: */
203 		gpu_write(gpu, REG_A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0001);
204 		/* Set up AOOO: */
205 		gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000003f);
206 		gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO, 0x003f003f);
207 		/* Enable 1K sort: */
208 		gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT, 0x0001003f);
209 		gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT_CONF, 0x000000a4);
210 		/* Disable VBIF clock gating. This is to enable AXI running
211 		 * higher frequency than GPU:
212 		 */
213 		gpu_write(gpu, REG_A3XX_VBIF_CLKON, 0x00000001);
214 
215 	} else {
216 		BUG();
217 	}
218 
219 	/* Make all blocks contribute to the GPU BUSY perf counter: */
220 	gpu_write(gpu, REG_A3XX_RBBM_GPU_BUSY_MASKED, 0xffffffff);
221 
222 	/* Tune the hystersis counters for SP and CP idle detection: */
223 	gpu_write(gpu, REG_A3XX_RBBM_SP_HYST_CNT, 0x10);
224 	gpu_write(gpu, REG_A3XX_RBBM_WAIT_IDLE_CLOCKS_CTL, 0x10);
225 
226 	/* Enable the RBBM error reporting bits.  This lets us get
227 	 * useful information on failure:
228 	 */
229 	gpu_write(gpu, REG_A3XX_RBBM_AHB_CTL0, 0x00000001);
230 
231 	/* Enable AHB error reporting: */
232 	gpu_write(gpu, REG_A3XX_RBBM_AHB_CTL1, 0xa6ffffff);
233 
234 	/* Turn on the power counters: */
235 	gpu_write(gpu, REG_A3XX_RBBM_RBBM_CTL, 0x00030000);
236 
237 	/* Turn on hang detection - this spews a lot of useful information
238 	 * into the RBBM registers on a hang:
239 	 */
240 	gpu_write(gpu, REG_A3XX_RBBM_INTERFACE_HANG_INT_CTL, 0x00010fff);
241 
242 	/* Enable 64-byte cacheline size. HW Default is 32-byte (0x000000E0): */
243 	gpu_write(gpu, REG_A3XX_UCHE_CACHE_MODE_CONTROL_REG, 0x00000001);
244 
245 	/* Enable Clock gating: */
246 	if (adreno_is_a305b(adreno_gpu) ||
247 	    adreno_is_a306(adreno_gpu) ||
248 	    adreno_is_a306a(adreno_gpu))
249 		gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xaaaaaaaa);
250 	else if (adreno_is_a320(adreno_gpu))
251 		gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xbfffffff);
252 	else if (adreno_is_a330v2(adreno_gpu))
253 		gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xaaaaaaaa);
254 	else if (adreno_is_a330(adreno_gpu))
255 		gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xbffcffff);
256 
257 	if (adreno_is_a330v2(adreno_gpu))
258 		gpu_write(gpu, REG_A3XX_RBBM_GPR0_CTL, 0x05515455);
259 	else if (adreno_is_a330(adreno_gpu))
260 		gpu_write(gpu, REG_A3XX_RBBM_GPR0_CTL, 0x00000000);
261 
262 	/* Set the OCMEM base address for A330, etc */
263 	if (a3xx_gpu->ocmem.hdl) {
264 		gpu_write(gpu, REG_A3XX_RB_GMEM_BASE_ADDR,
265 			(unsigned int)(a3xx_gpu->ocmem.base >> 14));
266 	}
267 
268 	/* Turn on performance counters: */
269 	gpu_write(gpu, REG_A3XX_RBBM_PERFCTR_CTL, 0x01);
270 
271 	gpu_write(gpu, REG_A3XX_RBBM_INT_0_MASK, A3XX_INT0_MASK);
272 
273 	ret = adreno_hw_init(gpu);
274 	if (ret)
275 		return ret;
276 
277 	/*
278 	 * Use the default ringbuffer size and block size but disable the RPTR
279 	 * shadow
280 	 */
281 	gpu_write(gpu, REG_AXXX_CP_RB_CNTL,
282 		MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE);
283 
284 	/* Set the ringbuffer address */
285 	gpu_write(gpu, REG_AXXX_CP_RB_BASE, lower_32_bits(gpu->rb[0]->iova));
286 
287 	/* setup access protection: */
288 	gpu_write(gpu, REG_A3XX_CP_PROTECT_CTRL, 0x00000007);
289 
290 	/* RBBM registers */
291 	gpu_write(gpu, REG_A3XX_CP_PROTECT(0), 0x63000040);
292 	gpu_write(gpu, REG_A3XX_CP_PROTECT(1), 0x62000080);
293 	gpu_write(gpu, REG_A3XX_CP_PROTECT(2), 0x600000cc);
294 	gpu_write(gpu, REG_A3XX_CP_PROTECT(3), 0x60000108);
295 	gpu_write(gpu, REG_A3XX_CP_PROTECT(4), 0x64000140);
296 	gpu_write(gpu, REG_A3XX_CP_PROTECT(5), 0x66000400);
297 
298 	/* CP registers */
299 	gpu_write(gpu, REG_A3XX_CP_PROTECT(6), 0x65000700);
300 	gpu_write(gpu, REG_A3XX_CP_PROTECT(7), 0x610007d8);
301 	gpu_write(gpu, REG_A3XX_CP_PROTECT(8), 0x620007e0);
302 	gpu_write(gpu, REG_A3XX_CP_PROTECT(9), 0x61001178);
303 	gpu_write(gpu, REG_A3XX_CP_PROTECT(10), 0x64001180);
304 
305 	/* RB registers */
306 	gpu_write(gpu, REG_A3XX_CP_PROTECT(11), 0x60003300);
307 
308 	/* VBIF registers */
309 	gpu_write(gpu, REG_A3XX_CP_PROTECT(12), 0x6b00c000);
310 
311 	/* NOTE: PM4/micro-engine firmware registers look to be the same
312 	 * for a2xx and a3xx.. we could possibly push that part down to
313 	 * adreno_gpu base class.  Or push both PM4 and PFP but
314 	 * parameterize the pfp ucode addr/data registers..
315 	 */
316 
317 	/* Load PM4: */
318 	ptr = (uint32_t *)(adreno_gpu->fw[ADRENO_FW_PM4]->data);
319 	len = adreno_gpu->fw[ADRENO_FW_PM4]->size / 4;
320 	DBG("loading PM4 ucode version: %x", ptr[1]);
321 
322 	gpu_write(gpu, REG_AXXX_CP_DEBUG,
323 			AXXX_CP_DEBUG_DYNAMIC_CLK_DISABLE |
324 			AXXX_CP_DEBUG_MIU_128BIT_WRITE_ENABLE);
325 	gpu_write(gpu, REG_AXXX_CP_ME_RAM_WADDR, 0);
326 	for (i = 1; i < len; i++)
327 		gpu_write(gpu, REG_AXXX_CP_ME_RAM_DATA, ptr[i]);
328 
329 	/* Load PFP: */
330 	ptr = (uint32_t *)(adreno_gpu->fw[ADRENO_FW_PFP]->data);
331 	len = adreno_gpu->fw[ADRENO_FW_PFP]->size / 4;
332 	DBG("loading PFP ucode version: %x", ptr[5]);
333 
334 	gpu_write(gpu, REG_A3XX_CP_PFP_UCODE_ADDR, 0);
335 	for (i = 1; i < len; i++)
336 		gpu_write(gpu, REG_A3XX_CP_PFP_UCODE_DATA, ptr[i]);
337 
338 	/* CP ROQ queue sizes (bytes) - RB:16, ST:16, IB1:32, IB2:64 */
339 	if (adreno_is_a305(adreno_gpu) ||
340 	    adreno_is_a306(adreno_gpu) ||
341 	    adreno_is_a306a(adreno_gpu) ||
342 	    adreno_is_a320(adreno_gpu)) {
343 		gpu_write(gpu, REG_AXXX_CP_QUEUE_THRESHOLDS,
344 				AXXX_CP_QUEUE_THRESHOLDS_CSQ_IB1_START(2) |
345 				AXXX_CP_QUEUE_THRESHOLDS_CSQ_IB2_START(6) |
346 				AXXX_CP_QUEUE_THRESHOLDS_CSQ_ST_START(14));
347 	} else if (adreno_is_a330(adreno_gpu) || adreno_is_a305b(adreno_gpu)) {
348 		/* NOTE: this (value take from downstream android driver)
349 		 * includes some bits outside of the known bitfields.  But
350 		 * A330 has this "MERCIU queue" thing too, which might
351 		 * explain a new bitfield or reshuffling:
352 		 */
353 		gpu_write(gpu, REG_AXXX_CP_QUEUE_THRESHOLDS, 0x003e2008);
354 	}
355 
356 	/* clear ME_HALT to start micro engine */
357 	gpu_write(gpu, REG_AXXX_CP_ME_CNTL, 0);
358 
359 	return a3xx_me_init(gpu) ? 0 : -EINVAL;
360 }
361 
362 static void a3xx_recover(struct msm_gpu *gpu)
363 {
364 	int i;
365 
366 	adreno_dump_info(gpu);
367 
368 	for (i = 0; i < 8; i++) {
369 		printk("CP_SCRATCH_REG%d: %u\n", i,
370 			gpu_read(gpu, REG_AXXX_CP_SCRATCH_REG0 + i));
371 	}
372 
373 	/* dump registers before resetting gpu, if enabled: */
374 	if (hang_debug)
375 		a3xx_dump(gpu);
376 
377 	gpu_write(gpu, REG_A3XX_RBBM_SW_RESET_CMD, 1);
378 	gpu_read(gpu, REG_A3XX_RBBM_SW_RESET_CMD);
379 	gpu_write(gpu, REG_A3XX_RBBM_SW_RESET_CMD, 0);
380 	adreno_recover(gpu);
381 }
382 
383 static void a3xx_destroy(struct msm_gpu *gpu)
384 {
385 	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
386 	struct a3xx_gpu *a3xx_gpu = to_a3xx_gpu(adreno_gpu);
387 
388 	DBG("%s", gpu->name);
389 
390 	adreno_gpu_cleanup(adreno_gpu);
391 
392 	adreno_gpu_ocmem_cleanup(&a3xx_gpu->ocmem);
393 
394 	kfree(a3xx_gpu);
395 }
396 
397 static bool a3xx_idle(struct msm_gpu *gpu)
398 {
399 	/* wait for ringbuffer to drain: */
400 	if (!adreno_idle(gpu, gpu->rb[0]))
401 		return false;
402 
403 	/* then wait for GPU to finish: */
404 	if (spin_until(!(gpu_read(gpu, REG_A3XX_RBBM_STATUS) &
405 			A3XX_RBBM_STATUS_GPU_BUSY))) {
406 		DRM_ERROR("%s: timeout waiting for GPU to idle!\n", gpu->name);
407 
408 		/* TODO maybe we need to reset GPU here to recover from hang? */
409 		return false;
410 	}
411 
412 	return true;
413 }
414 
415 static irqreturn_t a3xx_irq(struct msm_gpu *gpu)
416 {
417 	uint32_t status;
418 
419 	status = gpu_read(gpu, REG_A3XX_RBBM_INT_0_STATUS);
420 	DBG("%s: %08x", gpu->name, status);
421 
422 	// TODO
423 
424 	gpu_write(gpu, REG_A3XX_RBBM_INT_CLEAR_CMD, status);
425 
426 	msm_gpu_retire(gpu);
427 
428 	return IRQ_HANDLED;
429 }
430 
431 static const unsigned int a3xx_registers[] = {
432 	0x0000, 0x0002, 0x0010, 0x0012, 0x0018, 0x0018, 0x0020, 0x0027,
433 	0x0029, 0x002b, 0x002e, 0x0033, 0x0040, 0x0042, 0x0050, 0x005c,
434 	0x0060, 0x006c, 0x0080, 0x0082, 0x0084, 0x0088, 0x0090, 0x00e5,
435 	0x00ea, 0x00ed, 0x0100, 0x0100, 0x0110, 0x0123, 0x01c0, 0x01c1,
436 	0x01c3, 0x01c5, 0x01c7, 0x01c7, 0x01d5, 0x01d9, 0x01dc, 0x01dd,
437 	0x01ea, 0x01ea, 0x01ee, 0x01f1, 0x01f5, 0x01f5, 0x01fc, 0x01ff,
438 	0x0440, 0x0440, 0x0443, 0x0443, 0x0445, 0x0445, 0x044d, 0x044f,
439 	0x0452, 0x0452, 0x0454, 0x046f, 0x047c, 0x047c, 0x047f, 0x047f,
440 	0x0578, 0x057f, 0x0600, 0x0602, 0x0605, 0x0607, 0x060a, 0x060e,
441 	0x0612, 0x0614, 0x0c01, 0x0c02, 0x0c06, 0x0c1d, 0x0c3d, 0x0c3f,
442 	0x0c48, 0x0c4b, 0x0c80, 0x0c80, 0x0c88, 0x0c8b, 0x0ca0, 0x0cb7,
443 	0x0cc0, 0x0cc1, 0x0cc6, 0x0cc7, 0x0ce4, 0x0ce5, 0x0e00, 0x0e05,
444 	0x0e0c, 0x0e0c, 0x0e22, 0x0e23, 0x0e41, 0x0e45, 0x0e64, 0x0e65,
445 	0x0e80, 0x0e82, 0x0e84, 0x0e89, 0x0ea0, 0x0ea1, 0x0ea4, 0x0ea7,
446 	0x0ec4, 0x0ecb, 0x0ee0, 0x0ee0, 0x0f00, 0x0f01, 0x0f03, 0x0f09,
447 	0x2040, 0x2040, 0x2044, 0x2044, 0x2048, 0x204d, 0x2068, 0x2069,
448 	0x206c, 0x206d, 0x2070, 0x2070, 0x2072, 0x2072, 0x2074, 0x2075,
449 	0x2079, 0x207a, 0x20c0, 0x20d3, 0x20e4, 0x20ef, 0x2100, 0x2109,
450 	0x210c, 0x210c, 0x210e, 0x210e, 0x2110, 0x2111, 0x2114, 0x2115,
451 	0x21e4, 0x21e4, 0x21ea, 0x21ea, 0x21ec, 0x21ed, 0x21f0, 0x21f0,
452 	0x2200, 0x2212, 0x2214, 0x2217, 0x221a, 0x221a, 0x2240, 0x227e,
453 	0x2280, 0x228b, 0x22c0, 0x22c0, 0x22c4, 0x22ce, 0x22d0, 0x22d8,
454 	0x22df, 0x22e6, 0x22e8, 0x22e9, 0x22ec, 0x22ec, 0x22f0, 0x22f7,
455 	0x22ff, 0x22ff, 0x2340, 0x2343, 0x2440, 0x2440, 0x2444, 0x2444,
456 	0x2448, 0x244d, 0x2468, 0x2469, 0x246c, 0x246d, 0x2470, 0x2470,
457 	0x2472, 0x2472, 0x2474, 0x2475, 0x2479, 0x247a, 0x24c0, 0x24d3,
458 	0x24e4, 0x24ef, 0x2500, 0x2509, 0x250c, 0x250c, 0x250e, 0x250e,
459 	0x2510, 0x2511, 0x2514, 0x2515, 0x25e4, 0x25e4, 0x25ea, 0x25ea,
460 	0x25ec, 0x25ed, 0x25f0, 0x25f0, 0x2600, 0x2612, 0x2614, 0x2617,
461 	0x261a, 0x261a, 0x2640, 0x267e, 0x2680, 0x268b, 0x26c0, 0x26c0,
462 	0x26c4, 0x26ce, 0x26d0, 0x26d8, 0x26df, 0x26e6, 0x26e8, 0x26e9,
463 	0x26ec, 0x26ec, 0x26f0, 0x26f7, 0x26ff, 0x26ff, 0x2740, 0x2743,
464 	0x300c, 0x300e, 0x301c, 0x301d, 0x302a, 0x302a, 0x302c, 0x302d,
465 	0x3030, 0x3031, 0x3034, 0x3036, 0x303c, 0x303c, 0x305e, 0x305f,
466 	~0   /* sentinel */
467 };
468 
469 /* would be nice to not have to duplicate the _show() stuff with printk(): */
470 static void a3xx_dump(struct msm_gpu *gpu)
471 {
472 	printk("status:   %08x\n",
473 			gpu_read(gpu, REG_A3XX_RBBM_STATUS));
474 	adreno_dump(gpu);
475 }
476 
477 static struct msm_gpu_state *a3xx_gpu_state_get(struct msm_gpu *gpu)
478 {
479 	struct msm_gpu_state *state = kzalloc_obj(*state);
480 
481 	if (!state)
482 		return ERR_PTR(-ENOMEM);
483 
484 	adreno_gpu_state_get(gpu, state);
485 
486 	state->rbbm_status = gpu_read(gpu, REG_A3XX_RBBM_STATUS);
487 
488 	return state;
489 }
490 
491 static u64 a3xx_gpu_busy(struct msm_gpu *gpu, unsigned long *out_sample_rate)
492 {
493 	u64 busy_cycles;
494 
495 	busy_cycles = gpu_read64(gpu, REG_A3XX_RBBM_PERFCTR_RBBM_1_LO);
496 	*out_sample_rate = clk_get_rate(gpu->core_clk);
497 
498 	return busy_cycles;
499 }
500 
501 static int a3xx_vbif_halt(struct msm_gpu *gpu)
502 {
503 	u32 ack;
504 	int ret;
505 
506 	gpu_write(gpu, REG_A3XX_VBIF_XIN_HALT_CTRL0,
507 		  A3XX_VBIF_XIN_HALT_CTRL0_MASK);
508 	ret = spin_until(((ack = gpu_read(gpu, REG_A3XX_VBIF_XIN_HALT_CTRL1)) &
509 			  A3XX_VBIF_XIN_HALT_CTRL0_MASK) ==
510 			 A3XX_VBIF_XIN_HALT_CTRL0_MASK);
511 	gpu_write(gpu, REG_A3XX_VBIF_XIN_HALT_CTRL0, 0);
512 
513 	if (ret)
514 		return -EBUSY;
515 
516 	return 0;
517 }
518 
519 static int a3xx_pm_suspend(struct msm_gpu *gpu)
520 {
521 	int ret;
522 
523 	if (!a3xx_idle(gpu))
524 		return -EBUSY;
525 
526 	ret = a3xx_vbif_halt(gpu);
527 	if (ret)
528 		return ret;
529 
530 	return msm_gpu_pm_suspend(gpu);
531 }
532 
533 static u32 a3xx_get_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
534 {
535 	ring->memptrs->rptr = gpu_read(gpu, REG_AXXX_CP_RB_RPTR);
536 	return ring->memptrs->rptr;
537 }
538 
539 static struct msm_gpu *a3xx_gpu_init(struct drm_device *dev)
540 {
541 	struct a3xx_gpu *a3xx_gpu = NULL;
542 	struct adreno_gpu *adreno_gpu;
543 	struct msm_gpu *gpu;
544 	struct msm_drm_private *priv = dev->dev_private;
545 	struct platform_device *pdev = priv->gpu_pdev;
546 	struct adreno_platform_config *config = pdev->dev.platform_data;
547 	struct icc_path *ocmem_icc_path;
548 	struct icc_path *icc_path;
549 	int ret;
550 
551 	if (!pdev) {
552 		DRM_DEV_ERROR(dev->dev, "no a3xx device\n");
553 		ret = -ENXIO;
554 		goto fail;
555 	}
556 
557 	a3xx_gpu = kzalloc_obj(*a3xx_gpu);
558 	if (!a3xx_gpu) {
559 		ret = -ENOMEM;
560 		goto fail;
561 	}
562 
563 	adreno_gpu = &a3xx_gpu->base;
564 	gpu = &adreno_gpu->base;
565 
566 	adreno_gpu->registers = a3xx_registers;
567 
568 	ret = adreno_gpu_init(dev, pdev, adreno_gpu, config->info->funcs, 1);
569 	if (ret)
570 		goto fail;
571 
572 	/* if needed, allocate gmem: */
573 	if (adreno_is_a330(adreno_gpu) || adreno_is_a305b(adreno_gpu)) {
574 		ret = adreno_gpu_ocmem_init(&adreno_gpu->base.pdev->dev,
575 					    adreno_gpu, &a3xx_gpu->ocmem);
576 		if (ret)
577 			goto fail;
578 	}
579 
580 	icc_path = devm_of_icc_get(&pdev->dev, "gfx-mem");
581 	if (IS_ERR(icc_path)) {
582 		ret = PTR_ERR(icc_path);
583 		goto fail;
584 	}
585 
586 	ocmem_icc_path = devm_of_icc_get(&pdev->dev, "ocmem");
587 	if (IS_ERR(ocmem_icc_path)) {
588 		ret = PTR_ERR(ocmem_icc_path);
589 		/* allow -ENODATA, ocmem icc is optional */
590 		if (ret != -ENODATA)
591 			goto fail;
592 		ocmem_icc_path = NULL;
593 	}
594 
595 
596 	/*
597 	 * Set the ICC path to maximum speed for now by multiplying the fastest
598 	 * frequency by the bus width (8). We'll want to scale this later on to
599 	 * improve battery life.
600 	 */
601 	icc_set_bw(icc_path, 0, Bps_to_icc(gpu->fast_rate) * 8);
602 	icc_set_bw(ocmem_icc_path, 0, Bps_to_icc(gpu->fast_rate) * 8);
603 
604 	return gpu;
605 
606 fail:
607 	if (a3xx_gpu)
608 		a3xx_destroy(&a3xx_gpu->base.base);
609 
610 	return ERR_PTR(ret);
611 }
612 
613 const struct adreno_gpu_funcs a3xx_gpu_funcs = {
614 	.base = {
615 		.get_param = adreno_get_param,
616 		.set_param = adreno_set_param,
617 		.hw_init = a3xx_hw_init,
618 		.pm_suspend = a3xx_pm_suspend,
619 		.pm_resume = msm_gpu_pm_resume,
620 		.recover = a3xx_recover,
621 		.submit = a3xx_submit,
622 		.active_ring = adreno_active_ring,
623 		.irq = a3xx_irq,
624 		.destroy = a3xx_destroy,
625 #if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP)
626 		.show = adreno_show,
627 #endif
628 		.gpu_busy = a3xx_gpu_busy,
629 		.gpu_state_get = a3xx_gpu_state_get,
630 		.gpu_state_put = adreno_gpu_state_put,
631 		.create_vm = adreno_create_vm,
632 		.get_rptr = a3xx_get_rptr,
633 	},
634 	.init = a3xx_gpu_init,
635 };
636