Linux Audio

Check our new training course

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