xref: /openbmc/linux/drivers/gpu/drm/msm/adreno/a2xx_gpu.c (revision 173940b3)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2018 The Linux Foundation. All rights reserved. */
3 
4 #include "a2xx_gpu.h"
5 #include "msm_gem.h"
6 #include "msm_mmu.h"
7 
8 extern bool hang_debug;
9 
10 static void a2xx_dump(struct msm_gpu *gpu);
11 static bool a2xx_idle(struct msm_gpu *gpu);
12 
13 static void a2xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
14 {
15 	struct msm_ringbuffer *ring = submit->ring;
16 	unsigned int i;
17 
18 	for (i = 0; i < submit->nr_cmds; i++) {
19 		switch (submit->cmd[i].type) {
20 		case MSM_SUBMIT_CMD_IB_TARGET_BUF:
21 			/* ignore IB-targets */
22 			break;
23 		case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
24 			/* ignore if there has not been a ctx switch: */
25 			if (gpu->cur_ctx_seqno == submit->queue->ctx->seqno)
26 				break;
27 			fallthrough;
28 		case MSM_SUBMIT_CMD_BUF:
29 			OUT_PKT3(ring, CP_INDIRECT_BUFFER_PFD, 2);
30 			OUT_RING(ring, lower_32_bits(submit->cmd[i].iova));
31 			OUT_RING(ring, submit->cmd[i].size);
32 			OUT_PKT2(ring);
33 			break;
34 		}
35 	}
36 
37 	OUT_PKT0(ring, REG_AXXX_CP_SCRATCH_REG2, 1);
38 	OUT_RING(ring, submit->seqno);
39 
40 	/* wait for idle before cache flush/interrupt */
41 	OUT_PKT3(ring, CP_WAIT_FOR_IDLE, 1);
42 	OUT_RING(ring, 0x00000000);
43 
44 	OUT_PKT3(ring, CP_EVENT_WRITE, 3);
45 	OUT_RING(ring, CACHE_FLUSH_TS);
46 	OUT_RING(ring, rbmemptr(ring, fence));
47 	OUT_RING(ring, submit->seqno);
48 	OUT_PKT3(ring, CP_INTERRUPT, 1);
49 	OUT_RING(ring, 0x80000000);
50 
51 	adreno_flush(gpu, ring, REG_AXXX_CP_RB_WPTR);
52 }
53 
54 static bool a2xx_me_init(struct msm_gpu *gpu)
55 {
56 	struct msm_ringbuffer *ring = gpu->rb[0];
57 
58 	OUT_PKT3(ring, CP_ME_INIT, 18);
59 
60 	/* All fields present (bits 9:0) */
61 	OUT_RING(ring, 0x000003ff);
62 	/* Disable/Enable Real-Time Stream processing (present but ignored) */
63 	OUT_RING(ring, 0x00000000);
64 	/* Enable (2D <-> 3D) implicit synchronization (present but ignored) */
65 	OUT_RING(ring, 0x00000000);
66 
67 	OUT_RING(ring, REG_A2XX_RB_SURFACE_INFO - 0x2000);
68 	OUT_RING(ring, REG_A2XX_PA_SC_WINDOW_OFFSET - 0x2000);
69 	OUT_RING(ring, REG_A2XX_VGT_MAX_VTX_INDX - 0x2000);
70 	OUT_RING(ring, REG_A2XX_SQ_PROGRAM_CNTL - 0x2000);
71 	OUT_RING(ring, REG_A2XX_RB_DEPTHCONTROL - 0x2000);
72 	OUT_RING(ring, REG_A2XX_PA_SU_POINT_SIZE - 0x2000);
73 	OUT_RING(ring, REG_A2XX_PA_SC_LINE_CNTL - 0x2000);
74 	OUT_RING(ring, REG_A2XX_PA_SU_POLY_OFFSET_FRONT_SCALE - 0x2000);
75 
76 	/* Vertex and Pixel Shader Start Addresses in instructions
77 	 * (3 DWORDS per instruction) */
78 	OUT_RING(ring, 0x80000180);
79 	/* Maximum Contexts */
80 	OUT_RING(ring, 0x00000001);
81 	/* Write Confirm Interval and The CP will wait the
82 	 * wait_interval * 16 clocks between polling  */
83 	OUT_RING(ring, 0x00000000);
84 	/* NQ and External Memory Swap */
85 	OUT_RING(ring, 0x00000000);
86 	/* protected mode error checking (0x1f2 is REG_AXXX_CP_INT_CNTL) */
87 	OUT_RING(ring, 0x200001f2);
88 	/* Disable header dumping and Header dump address */
89 	OUT_RING(ring, 0x00000000);
90 	/* Header dump size */
91 	OUT_RING(ring, 0x00000000);
92 
93 	/* enable protected mode */
94 	OUT_PKT3(ring, CP_SET_PROTECTED_MODE, 1);
95 	OUT_RING(ring, 1);
96 
97 	adreno_flush(gpu, ring, REG_AXXX_CP_RB_WPTR);
98 	return a2xx_idle(gpu);
99 }
100 
101 static int a2xx_hw_init(struct msm_gpu *gpu)
102 {
103 	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
104 	dma_addr_t pt_base, tran_error;
105 	uint32_t *ptr, len;
106 	int i, ret;
107 
108 	msm_gpummu_params(gpu->aspace->mmu, &pt_base, &tran_error);
109 
110 	DBG("%s", gpu->name);
111 
112 	/* halt ME to avoid ucode upload issues on a20x */
113 	gpu_write(gpu, REG_AXXX_CP_ME_CNTL, AXXX_CP_ME_CNTL_HALT);
114 
115 	gpu_write(gpu, REG_A2XX_RBBM_PM_OVERRIDE1, 0xfffffffe);
116 	gpu_write(gpu, REG_A2XX_RBBM_PM_OVERRIDE2, 0xffffffff);
117 
118 	/* note: kgsl uses 0x00000001 after first reset on a22x */
119 	gpu_write(gpu, REG_A2XX_RBBM_SOFT_RESET, 0xffffffff);
120 	msleep(30);
121 	gpu_write(gpu, REG_A2XX_RBBM_SOFT_RESET, 0x00000000);
122 
123 	if (adreno_is_a225(adreno_gpu))
124 		gpu_write(gpu, REG_A2XX_SQ_FLOW_CONTROL, 0x18000000);
125 
126 	/* note: kgsl uses 0x0000ffff for a20x */
127 	gpu_write(gpu, REG_A2XX_RBBM_CNTL, 0x00004442);
128 
129 	/* MPU: physical range */
130 	gpu_write(gpu, REG_A2XX_MH_MMU_MPU_BASE, 0x00000000);
131 	gpu_write(gpu, REG_A2XX_MH_MMU_MPU_END, 0xfffff000);
132 
133 	gpu_write(gpu, REG_A2XX_MH_MMU_CONFIG, A2XX_MH_MMU_CONFIG_MMU_ENABLE |
134 		A2XX_MH_MMU_CONFIG_RB_W_CLNT_BEHAVIOR(BEH_TRAN_RNG) |
135 		A2XX_MH_MMU_CONFIG_CP_W_CLNT_BEHAVIOR(BEH_TRAN_RNG) |
136 		A2XX_MH_MMU_CONFIG_CP_R0_CLNT_BEHAVIOR(BEH_TRAN_RNG) |
137 		A2XX_MH_MMU_CONFIG_CP_R1_CLNT_BEHAVIOR(BEH_TRAN_RNG) |
138 		A2XX_MH_MMU_CONFIG_CP_R2_CLNT_BEHAVIOR(BEH_TRAN_RNG) |
139 		A2XX_MH_MMU_CONFIG_CP_R3_CLNT_BEHAVIOR(BEH_TRAN_RNG) |
140 		A2XX_MH_MMU_CONFIG_CP_R4_CLNT_BEHAVIOR(BEH_TRAN_RNG) |
141 		A2XX_MH_MMU_CONFIG_VGT_R0_CLNT_BEHAVIOR(BEH_TRAN_RNG) |
142 		A2XX_MH_MMU_CONFIG_VGT_R1_CLNT_BEHAVIOR(BEH_TRAN_RNG) |
143 		A2XX_MH_MMU_CONFIG_TC_R_CLNT_BEHAVIOR(BEH_TRAN_RNG) |
144 		A2XX_MH_MMU_CONFIG_PA_W_CLNT_BEHAVIOR(BEH_TRAN_RNG));
145 
146 	/* same as parameters in adreno_gpu */
147 	gpu_write(gpu, REG_A2XX_MH_MMU_VA_RANGE, SZ_16M |
148 		A2XX_MH_MMU_VA_RANGE_NUM_64KB_REGIONS(0xfff));
149 
150 	gpu_write(gpu, REG_A2XX_MH_MMU_PT_BASE, pt_base);
151 	gpu_write(gpu, REG_A2XX_MH_MMU_TRAN_ERROR, tran_error);
152 
153 	gpu_write(gpu, REG_A2XX_MH_MMU_INVALIDATE,
154 		A2XX_MH_MMU_INVALIDATE_INVALIDATE_ALL |
155 		A2XX_MH_MMU_INVALIDATE_INVALIDATE_TC);
156 
157 	gpu_write(gpu, REG_A2XX_MH_ARBITER_CONFIG,
158 		A2XX_MH_ARBITER_CONFIG_SAME_PAGE_LIMIT(16) |
159 		A2XX_MH_ARBITER_CONFIG_L1_ARB_ENABLE |
160 		A2XX_MH_ARBITER_CONFIG_L1_ARB_HOLD_ENABLE |
161 		A2XX_MH_ARBITER_CONFIG_PAGE_SIZE(1) |
162 		A2XX_MH_ARBITER_CONFIG_TC_REORDER_ENABLE |
163 		A2XX_MH_ARBITER_CONFIG_TC_ARB_HOLD_ENABLE |
164 		A2XX_MH_ARBITER_CONFIG_IN_FLIGHT_LIMIT_ENABLE |
165 		A2XX_MH_ARBITER_CONFIG_IN_FLIGHT_LIMIT(8) |
166 		A2XX_MH_ARBITER_CONFIG_CP_CLNT_ENABLE |
167 		A2XX_MH_ARBITER_CONFIG_VGT_CLNT_ENABLE |
168 		A2XX_MH_ARBITER_CONFIG_TC_CLNT_ENABLE |
169 		A2XX_MH_ARBITER_CONFIG_RB_CLNT_ENABLE |
170 		A2XX_MH_ARBITER_CONFIG_PA_CLNT_ENABLE);
171 	if (!adreno_is_a20x(adreno_gpu))
172 		gpu_write(gpu, REG_A2XX_MH_CLNT_INTF_CTRL_CONFIG1, 0x00032f07);
173 
174 	gpu_write(gpu, REG_A2XX_SQ_VS_PROGRAM, 0x00000000);
175 	gpu_write(gpu, REG_A2XX_SQ_PS_PROGRAM, 0x00000000);
176 
177 	gpu_write(gpu, REG_A2XX_RBBM_PM_OVERRIDE1, 0); /* 0x200 for msm8960? */
178 	gpu_write(gpu, REG_A2XX_RBBM_PM_OVERRIDE2, 0); /* 0x80/0x1a0 for a22x? */
179 
180 	/* note: gsl doesn't set this */
181 	gpu_write(gpu, REG_A2XX_RBBM_DEBUG, 0x00080000);
182 
183 	gpu_write(gpu, REG_A2XX_RBBM_INT_CNTL,
184 		A2XX_RBBM_INT_CNTL_RDERR_INT_MASK);
185 	gpu_write(gpu, REG_AXXX_CP_INT_CNTL,
186 		AXXX_CP_INT_CNTL_T0_PACKET_IN_IB_MASK |
187 		AXXX_CP_INT_CNTL_OPCODE_ERROR_MASK |
188 		AXXX_CP_INT_CNTL_PROTECTED_MODE_ERROR_MASK |
189 		AXXX_CP_INT_CNTL_RESERVED_BIT_ERROR_MASK |
190 		AXXX_CP_INT_CNTL_IB_ERROR_MASK |
191 		AXXX_CP_INT_CNTL_IB1_INT_MASK |
192 		AXXX_CP_INT_CNTL_RB_INT_MASK);
193 	gpu_write(gpu, REG_A2XX_SQ_INT_CNTL, 0);
194 	gpu_write(gpu, REG_A2XX_MH_INTERRUPT_MASK,
195 		A2XX_MH_INTERRUPT_MASK_AXI_READ_ERROR |
196 		A2XX_MH_INTERRUPT_MASK_AXI_WRITE_ERROR |
197 		A2XX_MH_INTERRUPT_MASK_MMU_PAGE_FAULT);
198 
199 	for (i = 3; i <= 5; i++)
200 		if ((SZ_16K << i) == adreno_gpu->gmem)
201 			break;
202 	gpu_write(gpu, REG_A2XX_RB_EDRAM_INFO, i);
203 
204 	ret = adreno_hw_init(gpu);
205 	if (ret)
206 		return ret;
207 
208 	gpu_write(gpu, REG_AXXX_CP_RB_CNTL,
209 		MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE);
210 
211 	gpu_write(gpu, REG_AXXX_CP_RB_BASE, lower_32_bits(gpu->rb[0]->iova));
212 
213 	/* NOTE: PM4/micro-engine firmware registers look to be the same
214 	 * for a2xx and a3xx.. we could possibly push that part down to
215 	 * adreno_gpu base class.  Or push both PM4 and PFP but
216 	 * parameterize the pfp ucode addr/data registers..
217 	 */
218 
219 	/* Load PM4: */
220 	ptr = (uint32_t *)(adreno_gpu->fw[ADRENO_FW_PM4]->data);
221 	len = adreno_gpu->fw[ADRENO_FW_PM4]->size / 4;
222 	DBG("loading PM4 ucode version: %x", ptr[1]);
223 
224 	gpu_write(gpu, REG_AXXX_CP_DEBUG,
225 			AXXX_CP_DEBUG_MIU_128BIT_WRITE_ENABLE);
226 	gpu_write(gpu, REG_AXXX_CP_ME_RAM_WADDR, 0);
227 	for (i = 1; i < len; i++)
228 		gpu_write(gpu, REG_AXXX_CP_ME_RAM_DATA, ptr[i]);
229 
230 	/* Load PFP: */
231 	ptr = (uint32_t *)(adreno_gpu->fw[ADRENO_FW_PFP]->data);
232 	len = adreno_gpu->fw[ADRENO_FW_PFP]->size / 4;
233 	DBG("loading PFP ucode version: %x", ptr[5]);
234 
235 	gpu_write(gpu, REG_A2XX_CP_PFP_UCODE_ADDR, 0);
236 	for (i = 1; i < len; i++)
237 		gpu_write(gpu, REG_A2XX_CP_PFP_UCODE_DATA, ptr[i]);
238 
239 	gpu_write(gpu, REG_AXXX_CP_QUEUE_THRESHOLDS, 0x000C0804);
240 
241 	/* clear ME_HALT to start micro engine */
242 	gpu_write(gpu, REG_AXXX_CP_ME_CNTL, 0);
243 
244 	return a2xx_me_init(gpu) ? 0 : -EINVAL;
245 }
246 
247 static void a2xx_recover(struct msm_gpu *gpu)
248 {
249 	int i;
250 
251 	adreno_dump_info(gpu);
252 
253 	for (i = 0; i < 8; i++) {
254 		printk("CP_SCRATCH_REG%d: %u\n", i,
255 			gpu_read(gpu, REG_AXXX_CP_SCRATCH_REG0 + i));
256 	}
257 
258 	/* dump registers before resetting gpu, if enabled: */
259 	if (hang_debug)
260 		a2xx_dump(gpu);
261 
262 	gpu_write(gpu, REG_A2XX_RBBM_SOFT_RESET, 1);
263 	gpu_read(gpu, REG_A2XX_RBBM_SOFT_RESET);
264 	gpu_write(gpu, REG_A2XX_RBBM_SOFT_RESET, 0);
265 	adreno_recover(gpu);
266 }
267 
268 static void a2xx_destroy(struct msm_gpu *gpu)
269 {
270 	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
271 	struct a2xx_gpu *a2xx_gpu = to_a2xx_gpu(adreno_gpu);
272 
273 	DBG("%s", gpu->name);
274 
275 	adreno_gpu_cleanup(adreno_gpu);
276 
277 	kfree(a2xx_gpu);
278 }
279 
280 static bool a2xx_idle(struct msm_gpu *gpu)
281 {
282 	/* wait for ringbuffer to drain: */
283 	if (!adreno_idle(gpu, gpu->rb[0]))
284 		return false;
285 
286 	/* then wait for GPU to finish: */
287 	if (spin_until(!(gpu_read(gpu, REG_A2XX_RBBM_STATUS) &
288 			A2XX_RBBM_STATUS_GUI_ACTIVE))) {
289 		DRM_ERROR("%s: timeout waiting for GPU to idle!\n", gpu->name);
290 
291 		/* TODO maybe we need to reset GPU here to recover from hang? */
292 		return false;
293 	}
294 
295 	return true;
296 }
297 
298 static irqreturn_t a2xx_irq(struct msm_gpu *gpu)
299 {
300 	uint32_t mstatus, status;
301 
302 	mstatus = gpu_read(gpu, REG_A2XX_MASTER_INT_SIGNAL);
303 
304 	if (mstatus & A2XX_MASTER_INT_SIGNAL_MH_INT_STAT) {
305 		status = gpu_read(gpu, REG_A2XX_MH_INTERRUPT_STATUS);
306 
307 		dev_warn(gpu->dev->dev, "MH_INT: %08X\n", status);
308 		dev_warn(gpu->dev->dev, "MMU_PAGE_FAULT: %08X\n",
309 			gpu_read(gpu, REG_A2XX_MH_MMU_PAGE_FAULT));
310 
311 		gpu_write(gpu, REG_A2XX_MH_INTERRUPT_CLEAR, status);
312 	}
313 
314 	if (mstatus & A2XX_MASTER_INT_SIGNAL_CP_INT_STAT) {
315 		status = gpu_read(gpu, REG_AXXX_CP_INT_STATUS);
316 
317 		/* only RB_INT is expected */
318 		if (status & ~AXXX_CP_INT_CNTL_RB_INT_MASK)
319 			dev_warn(gpu->dev->dev, "CP_INT: %08X\n", status);
320 
321 		gpu_write(gpu, REG_AXXX_CP_INT_ACK, status);
322 	}
323 
324 	if (mstatus & A2XX_MASTER_INT_SIGNAL_RBBM_INT_STAT) {
325 		status = gpu_read(gpu, REG_A2XX_RBBM_INT_STATUS);
326 
327 		dev_warn(gpu->dev->dev, "RBBM_INT: %08X\n", status);
328 
329 		gpu_write(gpu, REG_A2XX_RBBM_INT_ACK, status);
330 	}
331 
332 	msm_gpu_retire(gpu);
333 
334 	return IRQ_HANDLED;
335 }
336 
337 static const unsigned int a200_registers[] = {
338 	0x0000, 0x0002, 0x0004, 0x000B, 0x003B, 0x003D, 0x0040, 0x0044,
339 	0x0046, 0x0047, 0x01C0, 0x01C1, 0x01C3, 0x01C8, 0x01D5, 0x01D9,
340 	0x01DC, 0x01DD, 0x01EA, 0x01EA, 0x01EE, 0x01F3, 0x01F6, 0x01F7,
341 	0x01FC, 0x01FF, 0x0391, 0x0392, 0x039B, 0x039E, 0x03B2, 0x03B5,
342 	0x03B7, 0x03B7, 0x03F8, 0x03FB, 0x0440, 0x0440, 0x0443, 0x0444,
343 	0x044B, 0x044B, 0x044D, 0x044F, 0x0452, 0x0452, 0x0454, 0x045B,
344 	0x047F, 0x047F, 0x0578, 0x0587, 0x05C9, 0x05C9, 0x05D0, 0x05D0,
345 	0x0601, 0x0604, 0x0606, 0x0609, 0x060B, 0x060E, 0x0613, 0x0614,
346 	0x0A29, 0x0A2B, 0x0A2F, 0x0A31, 0x0A40, 0x0A43, 0x0A45, 0x0A45,
347 	0x0A4E, 0x0A4F, 0x0C2C, 0x0C2C, 0x0C30, 0x0C30, 0x0C38, 0x0C3C,
348 	0x0C40, 0x0C40, 0x0C44, 0x0C44, 0x0C80, 0x0C86, 0x0C88, 0x0C94,
349 	0x0C99, 0x0C9A, 0x0CA4, 0x0CA5, 0x0D00, 0x0D03, 0x0D06, 0x0D06,
350 	0x0D08, 0x0D0B, 0x0D34, 0x0D35, 0x0DAE, 0x0DC1, 0x0DC8, 0x0DD4,
351 	0x0DD8, 0x0DD9, 0x0E00, 0x0E00, 0x0E02, 0x0E04, 0x0E17, 0x0E1E,
352 	0x0EC0, 0x0EC9, 0x0ECB, 0x0ECC, 0x0ED0, 0x0ED0, 0x0ED4, 0x0ED7,
353 	0x0EE0, 0x0EE2, 0x0F01, 0x0F02, 0x0F0C, 0x0F0C, 0x0F0E, 0x0F12,
354 	0x0F26, 0x0F2A, 0x0F2C, 0x0F2C, 0x2000, 0x2002, 0x2006, 0x200F,
355 	0x2080, 0x2082, 0x2100, 0x2109, 0x210C, 0x2114, 0x2180, 0x2184,
356 	0x21F5, 0x21F7, 0x2200, 0x2208, 0x2280, 0x2283, 0x2293, 0x2294,
357 	0x2300, 0x2308, 0x2312, 0x2312, 0x2316, 0x231D, 0x2324, 0x2326,
358 	0x2380, 0x2383, 0x2400, 0x2402, 0x2406, 0x240F, 0x2480, 0x2482,
359 	0x2500, 0x2509, 0x250C, 0x2514, 0x2580, 0x2584, 0x25F5, 0x25F7,
360 	0x2600, 0x2608, 0x2680, 0x2683, 0x2693, 0x2694, 0x2700, 0x2708,
361 	0x2712, 0x2712, 0x2716, 0x271D, 0x2724, 0x2726, 0x2780, 0x2783,
362 	0x4000, 0x4003, 0x4800, 0x4805, 0x4900, 0x4900, 0x4908, 0x4908,
363 	~0   /* sentinel */
364 };
365 
366 static const unsigned int a220_registers[] = {
367 	0x0000, 0x0002, 0x0004, 0x000B, 0x003B, 0x003D, 0x0040, 0x0044,
368 	0x0046, 0x0047, 0x01C0, 0x01C1, 0x01C3, 0x01C8, 0x01D5, 0x01D9,
369 	0x01DC, 0x01DD, 0x01EA, 0x01EA, 0x01EE, 0x01F3, 0x01F6, 0x01F7,
370 	0x01FC, 0x01FF, 0x0391, 0x0392, 0x039B, 0x039E, 0x03B2, 0x03B5,
371 	0x03B7, 0x03B7, 0x03F8, 0x03FB, 0x0440, 0x0440, 0x0443, 0x0444,
372 	0x044B, 0x044B, 0x044D, 0x044F, 0x0452, 0x0452, 0x0454, 0x045B,
373 	0x047F, 0x047F, 0x0578, 0x0587, 0x05C9, 0x05C9, 0x05D0, 0x05D0,
374 	0x0601, 0x0604, 0x0606, 0x0609, 0x060B, 0x060E, 0x0613, 0x0614,
375 	0x0A29, 0x0A2B, 0x0A2F, 0x0A31, 0x0A40, 0x0A40, 0x0A42, 0x0A43,
376 	0x0A45, 0x0A45, 0x0A4E, 0x0A4F, 0x0C30, 0x0C30, 0x0C38, 0x0C39,
377 	0x0C3C, 0x0C3C, 0x0C80, 0x0C81, 0x0C88, 0x0C93, 0x0D00, 0x0D03,
378 	0x0D05, 0x0D06, 0x0D08, 0x0D0B, 0x0D34, 0x0D35, 0x0DAE, 0x0DC1,
379 	0x0DC8, 0x0DD4, 0x0DD8, 0x0DD9, 0x0E00, 0x0E00, 0x0E02, 0x0E04,
380 	0x0E17, 0x0E1E, 0x0EC0, 0x0EC9, 0x0ECB, 0x0ECC, 0x0ED0, 0x0ED0,
381 	0x0ED4, 0x0ED7, 0x0EE0, 0x0EE2, 0x0F01, 0x0F02, 0x2000, 0x2002,
382 	0x2006, 0x200F, 0x2080, 0x2082, 0x2100, 0x2102, 0x2104, 0x2109,
383 	0x210C, 0x2114, 0x2180, 0x2184, 0x21F5, 0x21F7, 0x2200, 0x2202,
384 	0x2204, 0x2204, 0x2208, 0x2208, 0x2280, 0x2282, 0x2294, 0x2294,
385 	0x2300, 0x2308, 0x2309, 0x230A, 0x2312, 0x2312, 0x2316, 0x2316,
386 	0x2318, 0x231D, 0x2324, 0x2326, 0x2380, 0x2383, 0x2400, 0x2402,
387 	0x2406, 0x240F, 0x2480, 0x2482, 0x2500, 0x2502, 0x2504, 0x2509,
388 	0x250C, 0x2514, 0x2580, 0x2584, 0x25F5, 0x25F7, 0x2600, 0x2602,
389 	0x2604, 0x2606, 0x2608, 0x2608, 0x2680, 0x2682, 0x2694, 0x2694,
390 	0x2700, 0x2708, 0x2712, 0x2712, 0x2716, 0x2716, 0x2718, 0x271D,
391 	0x2724, 0x2726, 0x2780, 0x2783, 0x4000, 0x4003, 0x4800, 0x4805,
392 	0x4900, 0x4900, 0x4908, 0x4908,
393 	~0   /* sentinel */
394 };
395 
396 static const unsigned int a225_registers[] = {
397 	0x0000, 0x0002, 0x0004, 0x000B, 0x003B, 0x003D, 0x0040, 0x0044,
398 	0x0046, 0x0047, 0x013C, 0x013C, 0x0140, 0x014F, 0x01C0, 0x01C1,
399 	0x01C3, 0x01C8, 0x01D5, 0x01D9, 0x01DC, 0x01DD, 0x01EA, 0x01EA,
400 	0x01EE, 0x01F3, 0x01F6, 0x01F7, 0x01FC, 0x01FF, 0x0391, 0x0392,
401 	0x039B, 0x039E, 0x03B2, 0x03B5, 0x03B7, 0x03B7, 0x03F8, 0x03FB,
402 	0x0440, 0x0440, 0x0443, 0x0444, 0x044B, 0x044B, 0x044D, 0x044F,
403 	0x0452, 0x0452, 0x0454, 0x045B, 0x047F, 0x047F, 0x0578, 0x0587,
404 	0x05C9, 0x05C9, 0x05D0, 0x05D0, 0x0601, 0x0604, 0x0606, 0x0609,
405 	0x060B, 0x060E, 0x0613, 0x0614, 0x0A29, 0x0A2B, 0x0A2F, 0x0A31,
406 	0x0A40, 0x0A40, 0x0A42, 0x0A43, 0x0A45, 0x0A45, 0x0A4E, 0x0A4F,
407 	0x0C01, 0x0C1D, 0x0C30, 0x0C30, 0x0C38, 0x0C39, 0x0C3C, 0x0C3C,
408 	0x0C80, 0x0C81, 0x0C88, 0x0C93, 0x0D00, 0x0D03, 0x0D05, 0x0D06,
409 	0x0D08, 0x0D0B, 0x0D34, 0x0D35, 0x0DAE, 0x0DC1, 0x0DC8, 0x0DD4,
410 	0x0DD8, 0x0DD9, 0x0E00, 0x0E00, 0x0E02, 0x0E04, 0x0E17, 0x0E1E,
411 	0x0EC0, 0x0EC9, 0x0ECB, 0x0ECC, 0x0ED0, 0x0ED0, 0x0ED4, 0x0ED7,
412 	0x0EE0, 0x0EE2, 0x0F01, 0x0F02, 0x2000, 0x200F, 0x2080, 0x2082,
413 	0x2100, 0x2109, 0x210C, 0x2114, 0x2180, 0x2184, 0x21F5, 0x21F7,
414 	0x2200, 0x2202, 0x2204, 0x2206, 0x2208, 0x2210, 0x2220, 0x2222,
415 	0x2280, 0x2282, 0x2294, 0x2294, 0x2297, 0x2297, 0x2300, 0x230A,
416 	0x2312, 0x2312, 0x2315, 0x2316, 0x2318, 0x231D, 0x2324, 0x2326,
417 	0x2340, 0x2357, 0x2360, 0x2360, 0x2380, 0x2383, 0x2400, 0x240F,
418 	0x2480, 0x2482, 0x2500, 0x2509, 0x250C, 0x2514, 0x2580, 0x2584,
419 	0x25F5, 0x25F7, 0x2600, 0x2602, 0x2604, 0x2606, 0x2608, 0x2610,
420 	0x2620, 0x2622, 0x2680, 0x2682, 0x2694, 0x2694, 0x2697, 0x2697,
421 	0x2700, 0x270A, 0x2712, 0x2712, 0x2715, 0x2716, 0x2718, 0x271D,
422 	0x2724, 0x2726, 0x2740, 0x2757, 0x2760, 0x2760, 0x2780, 0x2783,
423 	0x4000, 0x4003, 0x4800, 0x4806, 0x4808, 0x4808, 0x4900, 0x4900,
424 	0x4908, 0x4908,
425 	~0   /* sentinel */
426 };
427 
428 /* would be nice to not have to duplicate the _show() stuff with printk(): */
429 static void a2xx_dump(struct msm_gpu *gpu)
430 {
431 	printk("status:   %08x\n",
432 			gpu_read(gpu, REG_A2XX_RBBM_STATUS));
433 	adreno_dump(gpu);
434 }
435 
436 static struct msm_gpu_state *a2xx_gpu_state_get(struct msm_gpu *gpu)
437 {
438 	struct msm_gpu_state *state = kzalloc(sizeof(*state), GFP_KERNEL);
439 
440 	if (!state)
441 		return ERR_PTR(-ENOMEM);
442 
443 	adreno_gpu_state_get(gpu, state);
444 
445 	state->rbbm_status = gpu_read(gpu, REG_A2XX_RBBM_STATUS);
446 
447 	return state;
448 }
449 
450 static struct msm_gem_address_space *
451 a2xx_create_address_space(struct msm_gpu *gpu, struct platform_device *pdev)
452 {
453 	struct msm_mmu *mmu = msm_gpummu_new(&pdev->dev, gpu);
454 	struct msm_gem_address_space *aspace;
455 
456 	aspace = msm_gem_address_space_create(mmu, "gpu", SZ_16M,
457 		0xfff * SZ_64K);
458 
459 	if (IS_ERR(aspace) && !IS_ERR(mmu))
460 		mmu->funcs->destroy(mmu);
461 
462 	return aspace;
463 }
464 
465 static u32 a2xx_get_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
466 {
467 	ring->memptrs->rptr = gpu_read(gpu, REG_AXXX_CP_RB_RPTR);
468 	return ring->memptrs->rptr;
469 }
470 
471 static const struct adreno_gpu_funcs funcs = {
472 	.base = {
473 		.get_param = adreno_get_param,
474 		.set_param = adreno_set_param,
475 		.hw_init = a2xx_hw_init,
476 		.pm_suspend = msm_gpu_pm_suspend,
477 		.pm_resume = msm_gpu_pm_resume,
478 		.recover = a2xx_recover,
479 		.submit = a2xx_submit,
480 		.active_ring = adreno_active_ring,
481 		.irq = a2xx_irq,
482 		.destroy = a2xx_destroy,
483 #if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP)
484 		.show = adreno_show,
485 #endif
486 		.gpu_state_get = a2xx_gpu_state_get,
487 		.gpu_state_put = adreno_gpu_state_put,
488 		.create_address_space = a2xx_create_address_space,
489 		.get_rptr = a2xx_get_rptr,
490 	},
491 };
492 
493 static const struct msm_gpu_perfcntr perfcntrs[] = {
494 /* TODO */
495 };
496 
497 struct msm_gpu *a2xx_gpu_init(struct drm_device *dev)
498 {
499 	struct a2xx_gpu *a2xx_gpu = NULL;
500 	struct adreno_gpu *adreno_gpu;
501 	struct msm_gpu *gpu;
502 	struct msm_drm_private *priv = dev->dev_private;
503 	struct platform_device *pdev = priv->gpu_pdev;
504 	int ret;
505 
506 	if (!pdev) {
507 		dev_err(dev->dev, "no a2xx device\n");
508 		ret = -ENXIO;
509 		goto fail;
510 	}
511 
512 	a2xx_gpu = kzalloc(sizeof(*a2xx_gpu), GFP_KERNEL);
513 	if (!a2xx_gpu) {
514 		ret = -ENOMEM;
515 		goto fail;
516 	}
517 
518 	adreno_gpu = &a2xx_gpu->base;
519 	gpu = &adreno_gpu->base;
520 
521 	gpu->perfcntrs = perfcntrs;
522 	gpu->num_perfcntrs = ARRAY_SIZE(perfcntrs);
523 
524 	if (adreno_is_a20x(adreno_gpu))
525 		adreno_gpu->registers = a200_registers;
526 	else if (adreno_is_a225(adreno_gpu))
527 		adreno_gpu->registers = a225_registers;
528 	else
529 		adreno_gpu->registers = a220_registers;
530 
531 	ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1);
532 	if (ret)
533 		goto fail;
534 
535 	if (!gpu->aspace) {
536 		dev_err(dev->dev, "No memory protection without MMU\n");
537 		if (!allow_vram_carveout) {
538 			ret = -ENXIO;
539 			goto fail;
540 		}
541 	}
542 
543 	return gpu;
544 
545 fail:
546 	if (a2xx_gpu)
547 		a2xx_destroy(&a2xx_gpu->base.base);
548 
549 	return ERR_PTR(ret);
550 }
551