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 ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1); 544 if (ret) 545 goto fail; 546 547 if (adreno_is_a20x(adreno_gpu)) 548 adreno_gpu->registers = a200_registers; 549 else if (adreno_is_a225(adreno_gpu)) 550 adreno_gpu->registers = a225_registers; 551 else 552 adreno_gpu->registers = a220_registers; 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 } 570