2 * Copyright (C) 2013 Red Hat
3 * Author: Rob Clark <robdclark@gmail.com>
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
18 #ifdef CONFIG_MSM_OCMEM
19 # include <mach/ocmem.h>
24 #define A3XX_INT0_MASK \
25 (A3XX_INT0_RBBM_AHB_ERROR | \
26 A3XX_INT0_RBBM_ATB_BUS_OVERFLOW | \
27 A3XX_INT0_CP_T0_PACKET_IN_IB | \
28 A3XX_INT0_CP_OPCODE_ERROR | \
29 A3XX_INT0_CP_RESERVED_BIT_ERROR | \
30 A3XX_INT0_CP_HW_FAULT | \
31 A3XX_INT0_CP_IB1_INT | \
32 A3XX_INT0_CP_IB2_INT | \
33 A3XX_INT0_CP_RB_INT | \
34 A3XX_INT0_CP_REG_PROTECT_FAULT | \
35 A3XX_INT0_CP_AHB_ERROR_HALT | \
36 A3XX_INT0_UCHE_OOB_ACCESS)
38 extern bool hang_debug;
40 static void a3xx_dump(struct msm_gpu *gpu);
42 static void a3xx_me_init(struct msm_gpu *gpu)
44 struct msm_ringbuffer *ring = gpu->rb;
46 OUT_PKT3(ring, CP_ME_INIT, 17);
47 OUT_RING(ring, 0x000003f7);
48 OUT_RING(ring, 0x00000000);
49 OUT_RING(ring, 0x00000000);
50 OUT_RING(ring, 0x00000000);
51 OUT_RING(ring, 0x00000080);
52 OUT_RING(ring, 0x00000100);
53 OUT_RING(ring, 0x00000180);
54 OUT_RING(ring, 0x00006600);
55 OUT_RING(ring, 0x00000150);
56 OUT_RING(ring, 0x0000014e);
57 OUT_RING(ring, 0x00000154);
58 OUT_RING(ring, 0x00000001);
59 OUT_RING(ring, 0x00000000);
60 OUT_RING(ring, 0x00000000);
61 OUT_RING(ring, 0x00000000);
62 OUT_RING(ring, 0x00000000);
63 OUT_RING(ring, 0x00000000);
65 gpu->funcs->flush(gpu);
66 gpu->funcs->idle(gpu);
69 static int a3xx_hw_init(struct msm_gpu *gpu)
71 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
72 struct a3xx_gpu *a3xx_gpu = to_a3xx_gpu(adreno_gpu);
78 if (adreno_is_a305(adreno_gpu)) {
79 /* Set up 16 deep read/write request queues: */
80 gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF0, 0x10101010);
81 gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF1, 0x10101010);
82 gpu_write(gpu, REG_A3XX_VBIF_OUT_RD_LIM_CONF0, 0x10101010);
83 gpu_write(gpu, REG_A3XX_VBIF_OUT_WR_LIM_CONF0, 0x10101010);
84 gpu_write(gpu, REG_A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303);
85 gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF0, 0x10101010);
86 gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF1, 0x10101010);
88 gpu_write(gpu, REG_A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x0000ff);
89 /* Set up round robin arbitration between both AXI ports: */
90 gpu_write(gpu, REG_A3XX_VBIF_ARB_CTL, 0x00000030);
92 gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000003c);
93 gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO, 0x003c003c);
95 } else if (adreno_is_a320(adreno_gpu)) {
96 /* Set up 16 deep read/write request queues: */
97 gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF0, 0x10101010);
98 gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF1, 0x10101010);
99 gpu_write(gpu, REG_A3XX_VBIF_OUT_RD_LIM_CONF0, 0x10101010);
100 gpu_write(gpu, REG_A3XX_VBIF_OUT_WR_LIM_CONF0, 0x10101010);
101 gpu_write(gpu, REG_A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303);
102 gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF0, 0x10101010);
103 gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF1, 0x10101010);
105 gpu_write(gpu, REG_A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x0000ff);
106 /* Set up round robin arbitration between both AXI ports: */
107 gpu_write(gpu, REG_A3XX_VBIF_ARB_CTL, 0x00000030);
109 gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000003c);
110 gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO, 0x003c003c);
111 /* Enable 1K sort: */
112 gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT, 0x000000ff);
113 gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT_CONF, 0x000000a4);
115 } else if (adreno_is_a330v2(adreno_gpu)) {
117 * Most of the VBIF registers on 8974v2 have the correct
118 * values at power on, so we won't modify those if we don't
121 /* Enable 1k sort: */
122 gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT, 0x0001003f);
123 gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT_CONF, 0x000000a4);
125 gpu_write(gpu, REG_A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x00003f);
126 gpu_write(gpu, REG_A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303);
127 /* Set up VBIF_ROUND_ROBIN_QOS_ARB: */
128 gpu_write(gpu, REG_A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0003);
130 } else if (adreno_is_a330(adreno_gpu)) {
131 /* Set up 16 deep read/write request queues: */
132 gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF0, 0x18181818);
133 gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF1, 0x18181818);
134 gpu_write(gpu, REG_A3XX_VBIF_OUT_RD_LIM_CONF0, 0x18181818);
135 gpu_write(gpu, REG_A3XX_VBIF_OUT_WR_LIM_CONF0, 0x18181818);
136 gpu_write(gpu, REG_A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303);
137 gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF0, 0x18181818);
138 gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF1, 0x18181818);
140 gpu_write(gpu, REG_A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x00003f);
141 /* Set up round robin arbitration between both AXI ports: */
142 gpu_write(gpu, REG_A3XX_VBIF_ARB_CTL, 0x00000030);
143 /* Set up VBIF_ROUND_ROBIN_QOS_ARB: */
144 gpu_write(gpu, REG_A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0001);
146 gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000003f);
147 gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO, 0x003f003f);
148 /* Enable 1K sort: */
149 gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT, 0x0001003f);
150 gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT_CONF, 0x000000a4);
151 /* Disable VBIF clock gating. This is to enable AXI running
152 * higher frequency than GPU:
154 gpu_write(gpu, REG_A3XX_VBIF_CLKON, 0x00000001);
160 /* Make all blocks contribute to the GPU BUSY perf counter: */
161 gpu_write(gpu, REG_A3XX_RBBM_GPU_BUSY_MASKED, 0xffffffff);
163 /* Tune the hystersis counters for SP and CP idle detection: */
164 gpu_write(gpu, REG_A3XX_RBBM_SP_HYST_CNT, 0x10);
165 gpu_write(gpu, REG_A3XX_RBBM_WAIT_IDLE_CLOCKS_CTL, 0x10);
167 /* Enable the RBBM error reporting bits. This lets us get
168 * useful information on failure:
170 gpu_write(gpu, REG_A3XX_RBBM_AHB_CTL0, 0x00000001);
172 /* Enable AHB error reporting: */
173 gpu_write(gpu, REG_A3XX_RBBM_AHB_CTL1, 0xa6ffffff);
175 /* Turn on the power counters: */
176 gpu_write(gpu, REG_A3XX_RBBM_RBBM_CTL, 0x00030000);
178 /* Turn on hang detection - this spews a lot of useful information
179 * into the RBBM registers on a hang:
181 gpu_write(gpu, REG_A3XX_RBBM_INTERFACE_HANG_INT_CTL, 0x00010fff);
183 /* Enable 64-byte cacheline size. HW Default is 32-byte (0x000000E0): */
184 gpu_write(gpu, REG_A3XX_UCHE_CACHE_MODE_CONTROL_REG, 0x00000001);
186 /* Enable Clock gating: */
187 if (adreno_is_a320(adreno_gpu))
188 gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xbfffffff);
189 else if (adreno_is_a330v2(adreno_gpu))
190 gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xaaaaaaaa);
191 else if (adreno_is_a330(adreno_gpu))
192 gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xbffcffff);
194 if (adreno_is_a330v2(adreno_gpu))
195 gpu_write(gpu, REG_A3XX_RBBM_GPR0_CTL, 0x05515455);
196 else if (adreno_is_a330(adreno_gpu))
197 gpu_write(gpu, REG_A3XX_RBBM_GPR0_CTL, 0x00000000);
199 /* Set the OCMEM base address for A330, etc */
200 if (a3xx_gpu->ocmem_hdl) {
201 gpu_write(gpu, REG_A3XX_RB_GMEM_BASE_ADDR,
202 (unsigned int)(a3xx_gpu->ocmem_base >> 14));
205 /* Turn on performance counters: */
206 gpu_write(gpu, REG_A3XX_RBBM_PERFCTR_CTL, 0x01);
208 /* Enable the perfcntrs that we use.. */
209 for (i = 0; i < gpu->num_perfcntrs; i++) {
210 const struct msm_gpu_perfcntr *perfcntr = &gpu->perfcntrs[i];
211 gpu_write(gpu, perfcntr->select_reg, perfcntr->select_val);
214 gpu_write(gpu, REG_A3XX_RBBM_INT_0_MASK, A3XX_INT0_MASK);
216 ret = adreno_hw_init(gpu);
220 /* setup access protection: */
221 gpu_write(gpu, REG_A3XX_CP_PROTECT_CTRL, 0x00000007);
224 gpu_write(gpu, REG_A3XX_CP_PROTECT(0), 0x63000040);
225 gpu_write(gpu, REG_A3XX_CP_PROTECT(1), 0x62000080);
226 gpu_write(gpu, REG_A3XX_CP_PROTECT(2), 0x600000cc);
227 gpu_write(gpu, REG_A3XX_CP_PROTECT(3), 0x60000108);
228 gpu_write(gpu, REG_A3XX_CP_PROTECT(4), 0x64000140);
229 gpu_write(gpu, REG_A3XX_CP_PROTECT(5), 0x66000400);
232 gpu_write(gpu, REG_A3XX_CP_PROTECT(6), 0x65000700);
233 gpu_write(gpu, REG_A3XX_CP_PROTECT(7), 0x610007d8);
234 gpu_write(gpu, REG_A3XX_CP_PROTECT(8), 0x620007e0);
235 gpu_write(gpu, REG_A3XX_CP_PROTECT(9), 0x61001178);
236 gpu_write(gpu, REG_A3XX_CP_PROTECT(10), 0x64001180);
239 gpu_write(gpu, REG_A3XX_CP_PROTECT(11), 0x60003300);
242 gpu_write(gpu, REG_A3XX_CP_PROTECT(12), 0x6b00c000);
244 /* NOTE: PM4/micro-engine firmware registers look to be the same
245 * for a2xx and a3xx.. we could possibly push that part down to
246 * adreno_gpu base class. Or push both PM4 and PFP but
247 * parameterize the pfp ucode addr/data registers..
251 ptr = (uint32_t *)(adreno_gpu->pm4->data);
252 len = adreno_gpu->pm4->size / 4;
253 DBG("loading PM4 ucode version: %x", ptr[1]);
255 gpu_write(gpu, REG_AXXX_CP_DEBUG,
256 AXXX_CP_DEBUG_DYNAMIC_CLK_DISABLE |
257 AXXX_CP_DEBUG_MIU_128BIT_WRITE_ENABLE);
258 gpu_write(gpu, REG_AXXX_CP_ME_RAM_WADDR, 0);
259 for (i = 1; i < len; i++)
260 gpu_write(gpu, REG_AXXX_CP_ME_RAM_DATA, ptr[i]);
263 ptr = (uint32_t *)(adreno_gpu->pfp->data);
264 len = adreno_gpu->pfp->size / 4;
265 DBG("loading PFP ucode version: %x", ptr[5]);
267 gpu_write(gpu, REG_A3XX_CP_PFP_UCODE_ADDR, 0);
268 for (i = 1; i < len; i++)
269 gpu_write(gpu, REG_A3XX_CP_PFP_UCODE_DATA, ptr[i]);
271 /* CP ROQ queue sizes (bytes) - RB:16, ST:16, IB1:32, IB2:64 */
272 if (adreno_is_a305(adreno_gpu) || adreno_is_a320(adreno_gpu)) {
273 gpu_write(gpu, REG_AXXX_CP_QUEUE_THRESHOLDS,
274 AXXX_CP_QUEUE_THRESHOLDS_CSQ_IB1_START(2) |
275 AXXX_CP_QUEUE_THRESHOLDS_CSQ_IB2_START(6) |
276 AXXX_CP_QUEUE_THRESHOLDS_CSQ_ST_START(14));
277 } else if (adreno_is_a330(adreno_gpu)) {
278 /* NOTE: this (value take from downstream android driver)
279 * includes some bits outside of the known bitfields. But
280 * A330 has this "MERCIU queue" thing too, which might
281 * explain a new bitfield or reshuffling:
283 gpu_write(gpu, REG_AXXX_CP_QUEUE_THRESHOLDS, 0x003e2008);
286 /* clear ME_HALT to start micro engine */
287 gpu_write(gpu, REG_AXXX_CP_ME_CNTL, 0);
294 static void a3xx_recover(struct msm_gpu *gpu)
296 /* dump registers before resetting gpu, if enabled: */
299 gpu_write(gpu, REG_A3XX_RBBM_SW_RESET_CMD, 1);
300 gpu_read(gpu, REG_A3XX_RBBM_SW_RESET_CMD);
301 gpu_write(gpu, REG_A3XX_RBBM_SW_RESET_CMD, 0);
305 static void a3xx_destroy(struct msm_gpu *gpu)
307 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
308 struct a3xx_gpu *a3xx_gpu = to_a3xx_gpu(adreno_gpu);
310 DBG("%s", gpu->name);
312 adreno_gpu_cleanup(adreno_gpu);
314 #ifdef CONFIG_MSM_OCMEM
315 if (a3xx_gpu->ocmem_base)
316 ocmem_free(OCMEM_GRAPHICS, a3xx_gpu->ocmem_hdl);
322 static void a3xx_idle(struct msm_gpu *gpu)
324 /* wait for ringbuffer to drain: */
327 /* then wait for GPU to finish: */
328 if (spin_until(!(gpu_read(gpu, REG_A3XX_RBBM_STATUS) &
329 A3XX_RBBM_STATUS_GPU_BUSY)))
330 DRM_ERROR("%s: timeout waiting for GPU to idle!\n", gpu->name);
332 /* TODO maybe we need to reset GPU here to recover from hang? */
335 static irqreturn_t a3xx_irq(struct msm_gpu *gpu)
339 status = gpu_read(gpu, REG_A3XX_RBBM_INT_0_STATUS);
340 DBG("%s: %08x", gpu->name, status);
344 gpu_write(gpu, REG_A3XX_RBBM_INT_CLEAR_CMD, status);
351 static const unsigned int a3xx_registers[] = {
352 0x0000, 0x0002, 0x0010, 0x0012, 0x0018, 0x0018, 0x0020, 0x0027,
353 0x0029, 0x002b, 0x002e, 0x0033, 0x0040, 0x0042, 0x0050, 0x005c,
354 0x0060, 0x006c, 0x0080, 0x0082, 0x0084, 0x0088, 0x0090, 0x00e5,
355 0x00ea, 0x00ed, 0x0100, 0x0100, 0x0110, 0x0123, 0x01c0, 0x01c1,
356 0x01c3, 0x01c5, 0x01c7, 0x01c7, 0x01d5, 0x01d9, 0x01dc, 0x01dd,
357 0x01ea, 0x01ea, 0x01ee, 0x01f1, 0x01f5, 0x01f5, 0x01fc, 0x01ff,
358 0x0440, 0x0440, 0x0443, 0x0443, 0x0445, 0x0445, 0x044d, 0x044f,
359 0x0452, 0x0452, 0x0454, 0x046f, 0x047c, 0x047c, 0x047f, 0x047f,
360 0x0578, 0x057f, 0x0600, 0x0602, 0x0605, 0x0607, 0x060a, 0x060e,
361 0x0612, 0x0614, 0x0c01, 0x0c02, 0x0c06, 0x0c1d, 0x0c3d, 0x0c3f,
362 0x0c48, 0x0c4b, 0x0c80, 0x0c80, 0x0c88, 0x0c8b, 0x0ca0, 0x0cb7,
363 0x0cc0, 0x0cc1, 0x0cc6, 0x0cc7, 0x0ce4, 0x0ce5, 0x0e00, 0x0e05,
364 0x0e0c, 0x0e0c, 0x0e22, 0x0e23, 0x0e41, 0x0e45, 0x0e64, 0x0e65,
365 0x0e80, 0x0e82, 0x0e84, 0x0e89, 0x0ea0, 0x0ea1, 0x0ea4, 0x0ea7,
366 0x0ec4, 0x0ecb, 0x0ee0, 0x0ee0, 0x0f00, 0x0f01, 0x0f03, 0x0f09,
367 0x2040, 0x2040, 0x2044, 0x2044, 0x2048, 0x204d, 0x2068, 0x2069,
368 0x206c, 0x206d, 0x2070, 0x2070, 0x2072, 0x2072, 0x2074, 0x2075,
369 0x2079, 0x207a, 0x20c0, 0x20d3, 0x20e4, 0x20ef, 0x2100, 0x2109,
370 0x210c, 0x210c, 0x210e, 0x210e, 0x2110, 0x2111, 0x2114, 0x2115,
371 0x21e4, 0x21e4, 0x21ea, 0x21ea, 0x21ec, 0x21ed, 0x21f0, 0x21f0,
372 0x2200, 0x2212, 0x2214, 0x2217, 0x221a, 0x221a, 0x2240, 0x227e,
373 0x2280, 0x228b, 0x22c0, 0x22c0, 0x22c4, 0x22ce, 0x22d0, 0x22d8,
374 0x22df, 0x22e6, 0x22e8, 0x22e9, 0x22ec, 0x22ec, 0x22f0, 0x22f7,
375 0x22ff, 0x22ff, 0x2340, 0x2343, 0x2348, 0x2349, 0x2350, 0x2356,
376 0x2360, 0x2360, 0x2440, 0x2440, 0x2444, 0x2444, 0x2448, 0x244d,
377 0x2468, 0x2469, 0x246c, 0x246d, 0x2470, 0x2470, 0x2472, 0x2472,
378 0x2474, 0x2475, 0x2479, 0x247a, 0x24c0, 0x24d3, 0x24e4, 0x24ef,
379 0x2500, 0x2509, 0x250c, 0x250c, 0x250e, 0x250e, 0x2510, 0x2511,
380 0x2514, 0x2515, 0x25e4, 0x25e4, 0x25ea, 0x25ea, 0x25ec, 0x25ed,
381 0x25f0, 0x25f0, 0x2600, 0x2612, 0x2614, 0x2617, 0x261a, 0x261a,
382 0x2640, 0x267e, 0x2680, 0x268b, 0x26c0, 0x26c0, 0x26c4, 0x26ce,
383 0x26d0, 0x26d8, 0x26df, 0x26e6, 0x26e8, 0x26e9, 0x26ec, 0x26ec,
384 0x26f0, 0x26f7, 0x26ff, 0x26ff, 0x2740, 0x2743, 0x2748, 0x2749,
385 0x2750, 0x2756, 0x2760, 0x2760, 0x300c, 0x300e, 0x301c, 0x301d,
386 0x302a, 0x302a, 0x302c, 0x302d, 0x3030, 0x3031, 0x3034, 0x3036,
387 0x303c, 0x303c, 0x305e, 0x305f,
391 #ifdef CONFIG_DEBUG_FS
392 static void a3xx_show(struct msm_gpu *gpu, struct seq_file *m)
394 gpu->funcs->pm_resume(gpu);
395 seq_printf(m, "status: %08x\n",
396 gpu_read(gpu, REG_A3XX_RBBM_STATUS));
397 gpu->funcs->pm_suspend(gpu);
402 /* would be nice to not have to duplicate the _show() stuff with printk(): */
403 static void a3xx_dump(struct msm_gpu *gpu)
405 printk("status: %08x\n",
406 gpu_read(gpu, REG_A3XX_RBBM_STATUS));
410 static const struct adreno_gpu_funcs funcs = {
412 .get_param = adreno_get_param,
413 .hw_init = a3xx_hw_init,
414 .pm_suspend = msm_gpu_pm_suspend,
415 .pm_resume = msm_gpu_pm_resume,
416 .recover = a3xx_recover,
417 .last_fence = adreno_last_fence,
418 .submit = adreno_submit,
419 .flush = adreno_flush,
422 .destroy = a3xx_destroy,
423 #ifdef CONFIG_DEBUG_FS
429 static const struct msm_gpu_perfcntr perfcntrs[] = {
430 { REG_A3XX_SP_PERFCOUNTER6_SELECT, REG_A3XX_RBBM_PERFCTR_SP_6_LO,
431 SP_ALU_ACTIVE_CYCLES, "ALUACTIVE" },
432 { REG_A3XX_SP_PERFCOUNTER7_SELECT, REG_A3XX_RBBM_PERFCTR_SP_7_LO,
433 SP_FS_FULL_ALU_INSTRUCTIONS, "ALUFULL" },
436 struct msm_gpu *a3xx_gpu_init(struct drm_device *dev)
438 struct a3xx_gpu *a3xx_gpu = NULL;
439 struct adreno_gpu *adreno_gpu;
441 struct msm_drm_private *priv = dev->dev_private;
442 struct platform_device *pdev = priv->gpu_pdev;
446 dev_err(dev->dev, "no a3xx device\n");
451 a3xx_gpu = kzalloc(sizeof(*a3xx_gpu), GFP_KERNEL);
457 adreno_gpu = &a3xx_gpu->base;
458 gpu = &adreno_gpu->base;
460 a3xx_gpu->pdev = pdev;
462 gpu->perfcntrs = perfcntrs;
463 gpu->num_perfcntrs = ARRAY_SIZE(perfcntrs);
465 adreno_gpu->registers = a3xx_registers;
467 ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs);
471 /* if needed, allocate gmem: */
472 if (adreno_is_a330(adreno_gpu)) {
473 #ifdef CONFIG_MSM_OCMEM
474 /* TODO this is different/missing upstream: */
475 struct ocmem_buf *ocmem_hdl =
476 ocmem_allocate(OCMEM_GRAPHICS, adreno_gpu->gmem);
478 a3xx_gpu->ocmem_hdl = ocmem_hdl;
479 a3xx_gpu->ocmem_base = ocmem_hdl->addr;
480 adreno_gpu->gmem = ocmem_hdl->len;
481 DBG("using %dK of OCMEM at 0x%08x", adreno_gpu->gmem / 1024,
482 a3xx_gpu->ocmem_base);
487 /* TODO we think it is possible to configure the GPU to
488 * restrict access to VRAM carveout. But the required
489 * registers are unknown. For now just bail out and
490 * limp along with just modesetting. If it turns out
491 * to not be possible to restrict access, then we must
492 * implement a cmdstream validator.
494 dev_err(dev->dev, "No memory protection without IOMMU\n");
503 a3xx_destroy(&a3xx_gpu->base.base);