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