Merge tag 'amlogic-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/khilman...
[linux-2.6-microblaze.git] / drivers / gpu / drm / msm / adreno / a2xx_gpu.c
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_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
55 static 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
102 static 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
248 static 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
269 static 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
281 static 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
299 static 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
338 static 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
367 static 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
397 static 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(): */
430 static 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
437 static 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
451 static struct msm_gem_address_space *
452 a2xx_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
466 static 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
472 static 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
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 }