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
a2xx_submit(struct msm_gpu * gpu,struct msm_gem_submit * submit)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
a2xx_me_init(struct msm_gpu * gpu)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
a2xx_hw_init(struct msm_gpu * gpu)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
a2xx_recover(struct msm_gpu * gpu)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
a2xx_destroy(struct msm_gpu * gpu)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
a2xx_idle(struct msm_gpu * gpu)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
a2xx_irq(struct msm_gpu * gpu)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(): */
a2xx_dump(struct msm_gpu * gpu)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
a2xx_gpu_state_get(struct msm_gpu * gpu)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 *
a2xx_create_address_space(struct msm_gpu * gpu,struct platform_device * pdev)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
a2xx_get_rptr(struct msm_gpu * gpu,struct msm_ringbuffer * ring)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
a2xx_gpu_init(struct drm_device * dev)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 }
551