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