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