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 /* NOTE: PM4/micro-engine firmware registers look to be the same 168 * for a2xx and a3xx.. we could possibly push that part down to 169 * adreno_gpu base class. Or push both PM4 and PFP but 170 * parameterize the pfp ucode addr/data registers.. 171 */ 172 173 /* Load PM4: */ 174 ptr = (uint32_t *)(adreno_gpu->fw[ADRENO_FW_PM4]->data); 175 len = adreno_gpu->fw[ADRENO_FW_PM4]->size / 4; 176 DBG("loading PM4 ucode version: %x", ptr[1]); 177 178 gpu_write(gpu, REG_AXXX_CP_DEBUG, 179 AXXX_CP_DEBUG_MIU_128BIT_WRITE_ENABLE); 180 gpu_write(gpu, REG_AXXX_CP_ME_RAM_WADDR, 0); 181 for (i = 1; i < len; i++) 182 gpu_write(gpu, REG_AXXX_CP_ME_RAM_DATA, ptr[i]); 183 184 /* Load PFP: */ 185 ptr = (uint32_t *)(adreno_gpu->fw[ADRENO_FW_PFP]->data); 186 len = adreno_gpu->fw[ADRENO_FW_PFP]->size / 4; 187 DBG("loading PFP ucode version: %x", ptr[5]); 188 189 gpu_write(gpu, REG_A2XX_CP_PFP_UCODE_ADDR, 0); 190 for (i = 1; i < len; i++) 191 gpu_write(gpu, REG_A2XX_CP_PFP_UCODE_DATA, ptr[i]); 192 193 gpu_write(gpu, REG_AXXX_CP_QUEUE_THRESHOLDS, 0x000C0804); 194 195 /* clear ME_HALT to start micro engine */ 196 gpu_write(gpu, REG_AXXX_CP_ME_CNTL, 0); 197 198 return a2xx_me_init(gpu) ? 0 : -EINVAL; 199 } 200 201 static void a2xx_recover(struct msm_gpu *gpu) 202 { 203 int i; 204 205 adreno_dump_info(gpu); 206 207 for (i = 0; i < 8; i++) { 208 printk("CP_SCRATCH_REG%d: %u\n", i, 209 gpu_read(gpu, REG_AXXX_CP_SCRATCH_REG0 + i)); 210 } 211 212 /* dump registers before resetting gpu, if enabled: */ 213 if (hang_debug) 214 a2xx_dump(gpu); 215 216 gpu_write(gpu, REG_A2XX_RBBM_SOFT_RESET, 1); 217 gpu_read(gpu, REG_A2XX_RBBM_SOFT_RESET); 218 gpu_write(gpu, REG_A2XX_RBBM_SOFT_RESET, 0); 219 adreno_recover(gpu); 220 } 221 222 static void a2xx_destroy(struct msm_gpu *gpu) 223 { 224 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 225 struct a2xx_gpu *a2xx_gpu = to_a2xx_gpu(adreno_gpu); 226 227 DBG("%s", gpu->name); 228 229 adreno_gpu_cleanup(adreno_gpu); 230 231 kfree(a2xx_gpu); 232 } 233 234 static bool a2xx_idle(struct msm_gpu *gpu) 235 { 236 /* wait for ringbuffer to drain: */ 237 if (!adreno_idle(gpu, gpu->rb[0])) 238 return false; 239 240 /* then wait for GPU to finish: */ 241 if (spin_until(!(gpu_read(gpu, REG_A2XX_RBBM_STATUS) & 242 A2XX_RBBM_STATUS_GUI_ACTIVE))) { 243 DRM_ERROR("%s: timeout waiting for GPU to idle!\n", gpu->name); 244 245 /* TODO maybe we need to reset GPU here to recover from hang? */ 246 return false; 247 } 248 249 return true; 250 } 251 252 static irqreturn_t a2xx_irq(struct msm_gpu *gpu) 253 { 254 uint32_t mstatus, status; 255 256 mstatus = gpu_read(gpu, REG_A2XX_MASTER_INT_SIGNAL); 257 258 if (mstatus & A2XX_MASTER_INT_SIGNAL_MH_INT_STAT) { 259 status = gpu_read(gpu, REG_A2XX_MH_INTERRUPT_STATUS); 260 261 dev_warn(gpu->dev->dev, "MH_INT: %08X\n", status); 262 dev_warn(gpu->dev->dev, "MMU_PAGE_FAULT: %08X\n", 263 gpu_read(gpu, REG_A2XX_MH_MMU_PAGE_FAULT)); 264 265 gpu_write(gpu, REG_A2XX_MH_INTERRUPT_CLEAR, status); 266 } 267 268 if (mstatus & A2XX_MASTER_INT_SIGNAL_CP_INT_STAT) { 269 status = gpu_read(gpu, REG_AXXX_CP_INT_STATUS); 270 271 /* only RB_INT is expected */ 272 if (status & ~AXXX_CP_INT_CNTL_RB_INT_MASK) 273 dev_warn(gpu->dev->dev, "CP_INT: %08X\n", status); 274 275 gpu_write(gpu, REG_AXXX_CP_INT_ACK, status); 276 } 277 278 if (mstatus & A2XX_MASTER_INT_SIGNAL_RBBM_INT_STAT) { 279 status = gpu_read(gpu, REG_A2XX_RBBM_INT_STATUS); 280 281 dev_warn(gpu->dev->dev, "RBBM_INT: %08X\n", status); 282 283 gpu_write(gpu, REG_A2XX_RBBM_INT_ACK, status); 284 } 285 286 msm_gpu_retire(gpu); 287 288 return IRQ_HANDLED; 289 } 290 291 static const unsigned int a200_registers[] = { 292 0x0000, 0x0002, 0x0004, 0x000B, 0x003B, 0x003D, 0x0040, 0x0044, 293 0x0046, 0x0047, 0x01C0, 0x01C1, 0x01C3, 0x01C8, 0x01D5, 0x01D9, 294 0x01DC, 0x01DD, 0x01EA, 0x01EA, 0x01EE, 0x01F3, 0x01F6, 0x01F7, 295 0x01FC, 0x01FF, 0x0391, 0x0392, 0x039B, 0x039E, 0x03B2, 0x03B5, 296 0x03B7, 0x03B7, 0x03F8, 0x03FB, 0x0440, 0x0440, 0x0443, 0x0444, 297 0x044B, 0x044B, 0x044D, 0x044F, 0x0452, 0x0452, 0x0454, 0x045B, 298 0x047F, 0x047F, 0x0578, 0x0587, 0x05C9, 0x05C9, 0x05D0, 0x05D0, 299 0x0601, 0x0604, 0x0606, 0x0609, 0x060B, 0x060E, 0x0613, 0x0614, 300 0x0A29, 0x0A2B, 0x0A2F, 0x0A31, 0x0A40, 0x0A43, 0x0A45, 0x0A45, 301 0x0A4E, 0x0A4F, 0x0C2C, 0x0C2C, 0x0C30, 0x0C30, 0x0C38, 0x0C3C, 302 0x0C40, 0x0C40, 0x0C44, 0x0C44, 0x0C80, 0x0C86, 0x0C88, 0x0C94, 303 0x0C99, 0x0C9A, 0x0CA4, 0x0CA5, 0x0D00, 0x0D03, 0x0D06, 0x0D06, 304 0x0D08, 0x0D0B, 0x0D34, 0x0D35, 0x0DAE, 0x0DC1, 0x0DC8, 0x0DD4, 305 0x0DD8, 0x0DD9, 0x0E00, 0x0E00, 0x0E02, 0x0E04, 0x0E17, 0x0E1E, 306 0x0EC0, 0x0EC9, 0x0ECB, 0x0ECC, 0x0ED0, 0x0ED0, 0x0ED4, 0x0ED7, 307 0x0EE0, 0x0EE2, 0x0F01, 0x0F02, 0x0F0C, 0x0F0C, 0x0F0E, 0x0F12, 308 0x0F26, 0x0F2A, 0x0F2C, 0x0F2C, 0x2000, 0x2002, 0x2006, 0x200F, 309 0x2080, 0x2082, 0x2100, 0x2109, 0x210C, 0x2114, 0x2180, 0x2184, 310 0x21F5, 0x21F7, 0x2200, 0x2208, 0x2280, 0x2283, 0x2293, 0x2294, 311 0x2300, 0x2308, 0x2312, 0x2312, 0x2316, 0x231D, 0x2324, 0x2326, 312 0x2380, 0x2383, 0x2400, 0x2402, 0x2406, 0x240F, 0x2480, 0x2482, 313 0x2500, 0x2509, 0x250C, 0x2514, 0x2580, 0x2584, 0x25F5, 0x25F7, 314 0x2600, 0x2608, 0x2680, 0x2683, 0x2693, 0x2694, 0x2700, 0x2708, 315 0x2712, 0x2712, 0x2716, 0x271D, 0x2724, 0x2726, 0x2780, 0x2783, 316 0x4000, 0x4003, 0x4800, 0x4805, 0x4900, 0x4900, 0x4908, 0x4908, 317 ~0 /* sentinel */ 318 }; 319 320 static const unsigned int a220_registers[] = { 321 0x0000, 0x0002, 0x0004, 0x000B, 0x003B, 0x003D, 0x0040, 0x0044, 322 0x0046, 0x0047, 0x01C0, 0x01C1, 0x01C3, 0x01C8, 0x01D5, 0x01D9, 323 0x01DC, 0x01DD, 0x01EA, 0x01EA, 0x01EE, 0x01F3, 0x01F6, 0x01F7, 324 0x01FC, 0x01FF, 0x0391, 0x0392, 0x039B, 0x039E, 0x03B2, 0x03B5, 325 0x03B7, 0x03B7, 0x03F8, 0x03FB, 0x0440, 0x0440, 0x0443, 0x0444, 326 0x044B, 0x044B, 0x044D, 0x044F, 0x0452, 0x0452, 0x0454, 0x045B, 327 0x047F, 0x047F, 0x0578, 0x0587, 0x05C9, 0x05C9, 0x05D0, 0x05D0, 328 0x0601, 0x0604, 0x0606, 0x0609, 0x060B, 0x060E, 0x0613, 0x0614, 329 0x0A29, 0x0A2B, 0x0A2F, 0x0A31, 0x0A40, 0x0A40, 0x0A42, 0x0A43, 330 0x0A45, 0x0A45, 0x0A4E, 0x0A4F, 0x0C30, 0x0C30, 0x0C38, 0x0C39, 331 0x0C3C, 0x0C3C, 0x0C80, 0x0C81, 0x0C88, 0x0C93, 0x0D00, 0x0D03, 332 0x0D05, 0x0D06, 0x0D08, 0x0D0B, 0x0D34, 0x0D35, 0x0DAE, 0x0DC1, 333 0x0DC8, 0x0DD4, 0x0DD8, 0x0DD9, 0x0E00, 0x0E00, 0x0E02, 0x0E04, 334 0x0E17, 0x0E1E, 0x0EC0, 0x0EC9, 0x0ECB, 0x0ECC, 0x0ED0, 0x0ED0, 335 0x0ED4, 0x0ED7, 0x0EE0, 0x0EE2, 0x0F01, 0x0F02, 0x2000, 0x2002, 336 0x2006, 0x200F, 0x2080, 0x2082, 0x2100, 0x2102, 0x2104, 0x2109, 337 0x210C, 0x2114, 0x2180, 0x2184, 0x21F5, 0x21F7, 0x2200, 0x2202, 338 0x2204, 0x2204, 0x2208, 0x2208, 0x2280, 0x2282, 0x2294, 0x2294, 339 0x2300, 0x2308, 0x2309, 0x230A, 0x2312, 0x2312, 0x2316, 0x2316, 340 0x2318, 0x231D, 0x2324, 0x2326, 0x2380, 0x2383, 0x2400, 0x2402, 341 0x2406, 0x240F, 0x2480, 0x2482, 0x2500, 0x2502, 0x2504, 0x2509, 342 0x250C, 0x2514, 0x2580, 0x2584, 0x25F5, 0x25F7, 0x2600, 0x2602, 343 0x2604, 0x2606, 0x2608, 0x2608, 0x2680, 0x2682, 0x2694, 0x2694, 344 0x2700, 0x2708, 0x2712, 0x2712, 0x2716, 0x2716, 0x2718, 0x271D, 345 0x2724, 0x2726, 0x2780, 0x2783, 0x4000, 0x4003, 0x4800, 0x4805, 346 0x4900, 0x4900, 0x4908, 0x4908, 347 ~0 /* sentinel */ 348 }; 349 350 static const unsigned int a225_registers[] = { 351 0x0000, 0x0002, 0x0004, 0x000B, 0x003B, 0x003D, 0x0040, 0x0044, 352 0x0046, 0x0047, 0x013C, 0x013C, 0x0140, 0x014F, 0x01C0, 0x01C1, 353 0x01C3, 0x01C8, 0x01D5, 0x01D9, 0x01DC, 0x01DD, 0x01EA, 0x01EA, 354 0x01EE, 0x01F3, 0x01F6, 0x01F7, 0x01FC, 0x01FF, 0x0391, 0x0392, 355 0x039B, 0x039E, 0x03B2, 0x03B5, 0x03B7, 0x03B7, 0x03F8, 0x03FB, 356 0x0440, 0x0440, 0x0443, 0x0444, 0x044B, 0x044B, 0x044D, 0x044F, 357 0x0452, 0x0452, 0x0454, 0x045B, 0x047F, 0x047F, 0x0578, 0x0587, 358 0x05C9, 0x05C9, 0x05D0, 0x05D0, 0x0601, 0x0604, 0x0606, 0x0609, 359 0x060B, 0x060E, 0x0613, 0x0614, 0x0A29, 0x0A2B, 0x0A2F, 0x0A31, 360 0x0A40, 0x0A40, 0x0A42, 0x0A43, 0x0A45, 0x0A45, 0x0A4E, 0x0A4F, 361 0x0C01, 0x0C1D, 0x0C30, 0x0C30, 0x0C38, 0x0C39, 0x0C3C, 0x0C3C, 362 0x0C80, 0x0C81, 0x0C88, 0x0C93, 0x0D00, 0x0D03, 0x0D05, 0x0D06, 363 0x0D08, 0x0D0B, 0x0D34, 0x0D35, 0x0DAE, 0x0DC1, 0x0DC8, 0x0DD4, 364 0x0DD8, 0x0DD9, 0x0E00, 0x0E00, 0x0E02, 0x0E04, 0x0E17, 0x0E1E, 365 0x0EC0, 0x0EC9, 0x0ECB, 0x0ECC, 0x0ED0, 0x0ED0, 0x0ED4, 0x0ED7, 366 0x0EE0, 0x0EE2, 0x0F01, 0x0F02, 0x2000, 0x200F, 0x2080, 0x2082, 367 0x2100, 0x2109, 0x210C, 0x2114, 0x2180, 0x2184, 0x21F5, 0x21F7, 368 0x2200, 0x2202, 0x2204, 0x2206, 0x2208, 0x2210, 0x2220, 0x2222, 369 0x2280, 0x2282, 0x2294, 0x2294, 0x2297, 0x2297, 0x2300, 0x230A, 370 0x2312, 0x2312, 0x2315, 0x2316, 0x2318, 0x231D, 0x2324, 0x2326, 371 0x2340, 0x2357, 0x2360, 0x2360, 0x2380, 0x2383, 0x2400, 0x240F, 372 0x2480, 0x2482, 0x2500, 0x2509, 0x250C, 0x2514, 0x2580, 0x2584, 373 0x25F5, 0x25F7, 0x2600, 0x2602, 0x2604, 0x2606, 0x2608, 0x2610, 374 0x2620, 0x2622, 0x2680, 0x2682, 0x2694, 0x2694, 0x2697, 0x2697, 375 0x2700, 0x270A, 0x2712, 0x2712, 0x2715, 0x2716, 0x2718, 0x271D, 376 0x2724, 0x2726, 0x2740, 0x2757, 0x2760, 0x2760, 0x2780, 0x2783, 377 0x4000, 0x4003, 0x4800, 0x4806, 0x4808, 0x4808, 0x4900, 0x4900, 378 0x4908, 0x4908, 379 ~0 /* sentinel */ 380 }; 381 382 /* would be nice to not have to duplicate the _show() stuff with printk(): */ 383 static void a2xx_dump(struct msm_gpu *gpu) 384 { 385 printk("status: %08x\n", 386 gpu_read(gpu, REG_A2XX_RBBM_STATUS)); 387 adreno_dump(gpu); 388 } 389 390 static struct msm_gpu_state *a2xx_gpu_state_get(struct msm_gpu *gpu) 391 { 392 struct msm_gpu_state *state = kzalloc(sizeof(*state), GFP_KERNEL); 393 394 if (!state) 395 return ERR_PTR(-ENOMEM); 396 397 adreno_gpu_state_get(gpu, state); 398 399 state->rbbm_status = gpu_read(gpu, REG_A2XX_RBBM_STATUS); 400 401 return state; 402 } 403 404 static struct msm_gem_address_space * 405 a2xx_create_address_space(struct msm_gpu *gpu, struct platform_device *pdev) 406 { 407 struct msm_mmu *mmu = msm_gpummu_new(&pdev->dev, gpu); 408 struct msm_gem_address_space *aspace; 409 410 aspace = msm_gem_address_space_create(mmu, "gpu", SZ_16M, 411 0xfff * SZ_64K); 412 413 if (IS_ERR(aspace) && !IS_ERR(mmu)) 414 mmu->funcs->destroy(mmu); 415 416 return aspace; 417 } 418 419 /* Register offset defines for A2XX - copy of A3XX */ 420 static const unsigned int a2xx_register_offsets[REG_ADRENO_REGISTER_MAX] = { 421 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_BASE, REG_AXXX_CP_RB_BASE), 422 REG_ADRENO_SKIP(REG_ADRENO_CP_RB_BASE_HI), 423 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR_ADDR, REG_AXXX_CP_RB_RPTR_ADDR), 424 REG_ADRENO_SKIP(REG_ADRENO_CP_RB_RPTR_ADDR_HI), 425 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR, REG_AXXX_CP_RB_RPTR), 426 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_WPTR, REG_AXXX_CP_RB_WPTR), 427 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_CNTL, REG_AXXX_CP_RB_CNTL), 428 }; 429 430 static const struct adreno_gpu_funcs funcs = { 431 .base = { 432 .get_param = adreno_get_param, 433 .hw_init = a2xx_hw_init, 434 .pm_suspend = msm_gpu_pm_suspend, 435 .pm_resume = msm_gpu_pm_resume, 436 .recover = a2xx_recover, 437 .submit = adreno_submit, 438 .flush = adreno_flush, 439 .active_ring = adreno_active_ring, 440 .irq = a2xx_irq, 441 .destroy = a2xx_destroy, 442 #if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP) 443 .show = adreno_show, 444 #endif 445 .gpu_state_get = a2xx_gpu_state_get, 446 .gpu_state_put = adreno_gpu_state_put, 447 .create_address_space = a2xx_create_address_space, 448 }, 449 }; 450 451 static const struct msm_gpu_perfcntr perfcntrs[] = { 452 /* TODO */ 453 }; 454 455 struct msm_gpu *a2xx_gpu_init(struct drm_device *dev) 456 { 457 struct a2xx_gpu *a2xx_gpu = NULL; 458 struct adreno_gpu *adreno_gpu; 459 struct msm_gpu *gpu; 460 struct msm_drm_private *priv = dev->dev_private; 461 struct platform_device *pdev = priv->gpu_pdev; 462 int ret; 463 464 if (!pdev) { 465 dev_err(dev->dev, "no a2xx device\n"); 466 ret = -ENXIO; 467 goto fail; 468 } 469 470 a2xx_gpu = kzalloc(sizeof(*a2xx_gpu), GFP_KERNEL); 471 if (!a2xx_gpu) { 472 ret = -ENOMEM; 473 goto fail; 474 } 475 476 adreno_gpu = &a2xx_gpu->base; 477 gpu = &adreno_gpu->base; 478 479 gpu->perfcntrs = perfcntrs; 480 gpu->num_perfcntrs = ARRAY_SIZE(perfcntrs); 481 482 if (adreno_is_a20x(adreno_gpu)) 483 adreno_gpu->registers = a200_registers; 484 else if (adreno_is_a225(adreno_gpu)) 485 adreno_gpu->registers = a225_registers; 486 else 487 adreno_gpu->registers = a220_registers; 488 489 adreno_gpu->reg_offsets = a2xx_register_offsets; 490 491 ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1); 492 if (ret) 493 goto fail; 494 495 if (!gpu->aspace) { 496 dev_err(dev->dev, "No memory protection without MMU\n"); 497 ret = -ENXIO; 498 goto fail; 499 } 500 501 return gpu; 502 503 fail: 504 if (a2xx_gpu) 505 a2xx_destroy(&a2xx_gpu->base.base); 506 507 return ERR_PTR(ret); 508 } 509