50ee03bc94b49abde84dc0b7979ed2bfe12a3a23
[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_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 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
108 static 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
266 static 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
287 static 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
299 static 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
317 static 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
356 static 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
385 static 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
415 static 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(): */
448 static 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
455 static 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
469 static struct msm_gem_address_space *
470 a2xx_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
484 static 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
490 static 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
512 static const struct msm_gpu_perfcntr perfcntrs[] = {
513 /* TODO */
514 };
515
516 struct 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         if (adreno_is_a20x(adreno_gpu))
544                 adreno_gpu->registers = a200_registers;
545         else if (adreno_is_a225(adreno_gpu))
546                 adreno_gpu->registers = a225_registers;
547         else
548                 adreno_gpu->registers = a220_registers;
549
550         ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1);
551         if (ret)
552                 goto fail;
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
564 fail:
565         if (a2xx_gpu)
566                 a2xx_destroy(&a2xx_gpu->base.base);
567
568         return ERR_PTR(ret);
569 }