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