/** * adreno_context_restore() - generic context restore handler * @adreno_dev: the device * @context: the context * * Basic context restore handler that writes the context identifier * to the ringbuffer and issues pagetable switch commands if necessary. */ static int adreno_context_restore(struct adreno_device *adreno_dev, struct adreno_context *context) { struct kgsl_device *device; unsigned int cmds[8]; if (adreno_dev == NULL || context == NULL) return -EINVAL; device = &adreno_dev->dev; /* write the context identifier to the ringbuffer */ cmds[0] = cp_nop_packet(1); cmds[1] = KGSL_CONTEXT_TO_MEM_IDENTIFIER; cmds[2] = cp_type3_packet(CP_MEM_WRITE, 2); cmds[3] = device->memstore.gpuaddr + KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context); cmds[4] = context->base.id; /* Flush the UCHE for new context */ cmds[5] = cp_type0_packet( adreno_getreg(adreno_dev, ADRENO_REG_UCHE_INVALIDATE0), 2); cmds[6] = 0; if (adreno_is_a4xx(adreno_dev)) cmds[7] = 0x12; else if (adreno_is_a3xx(adreno_dev)) cmds[7] = 0x90000000; return adreno_ringbuffer_issuecmds(device, context, KGSL_CMD_FLAGS_NONE, cmds, 8); }
static void _snapshot_hlsq_regs(struct kgsl_snapshot_registers *regs, struct kgsl_snapshot_registers_list *list, struct adreno_device *adreno_dev) { if (!adreno_is_a3xx(adreno_dev)) { regs[list->count].regs = (unsigned int *) a3xx_hlsq_registers; regs[list->count].count = a3xx_hlsq_registers_count; list->count++; } }
/** * adreno_context_restore() - generic context restore handler * @rb: The RB in which context is to be restored * * Basic context restore handler that writes the context identifier * to the ringbuffer and issues pagetable switch commands if necessary. */ static void adreno_context_restore(struct adreno_ringbuffer *rb) { struct kgsl_device *device = rb->device; struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct adreno_context *drawctxt = rb->drawctxt_active; unsigned int cmds[11]; int ret; if (!drawctxt) return; /* * write the context identifier to the ringbuffer, write to both * the global index and the index of the RB in which the context * operates. The global values will always be reliable since we * could be in middle of RB switch in which case the RB value may * not be accurate */ cmds[0] = cp_nop_packet(1); cmds[1] = KGSL_CONTEXT_TO_MEM_IDENTIFIER; cmds[2] = cp_type3_packet(CP_MEM_WRITE, 2); cmds[3] = device->memstore.gpuaddr + KGSL_MEMSTORE_RB_OFFSET(rb, current_context); cmds[4] = drawctxt->base.id; cmds[5] = cp_type3_packet(CP_MEM_WRITE, 2); cmds[6] = device->memstore.gpuaddr + KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context); cmds[7] = drawctxt->base.id; /* Flush the UCHE for new context */ cmds[8] = cp_type0_packet( adreno_getreg(adreno_dev, ADRENO_REG_UCHE_INVALIDATE0), 2); cmds[9] = 0; if (adreno_is_a4xx(adreno_dev)) cmds[10] = 0x12; else if (adreno_is_a3xx(adreno_dev)) cmds[10] = 0x90000000; ret = adreno_ringbuffer_issuecmds(rb, KGSL_CMD_FLAGS_NONE, cmds, 11); if (ret) { /* * A failure to submit commands to ringbuffer means RB may * be full, in this case wait for idle and use CPU */ ret = adreno_idle(device); BUG_ON(ret); _adreno_context_restore_cpu(rb, drawctxt); } }
void adreno_ringbuffer_submit(struct adreno_ringbuffer *rb, struct adreno_submit_time *time) { struct adreno_device *adreno_dev = ADRENO_DEVICE(rb->device); BUG_ON(rb->wptr == 0); _cff_write_ringbuffer(rb); if (time != NULL) { unsigned long flags; local_irq_save(flags); if (!adreno_is_a3xx(adreno_dev)) { adreno_readreg64(adreno_dev, ADRENO_REG_RBBM_ALWAYSON_COUNTER_LO, ADRENO_REG_RBBM_ALWAYSON_COUNTER_HI, &time->ticks); if (ADRENO_GPUREV(adreno_dev) >= 400 && ADRENO_GPUREV(adreno_dev) <= ADRENO_REV_A530) time->ticks &= 0xFFFFFFFF; } else time->ticks = 0; time->ktime = local_clock(); getnstimeofday(&time->utime); local_irq_restore(flags); } mb(); if (adreno_preempt_state(adreno_dev, ADRENO_DISPATCHER_PREEMPT_CLEAR) && (adreno_dev->cur_rb == rb)) { kgsl_pwrscale_busy(rb->device); adreno_writereg(adreno_dev, ADRENO_REG_CP_RB_WPTR, rb->wptr); } }
int adreno_ringbuffer_load_pm4_ucode(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); int i; if (adreno_dev->pm4_fw == NULL) { int ret = adreno_ringbuffer_read_pm4_ucode(device); if (ret) return ret; } KGSL_DRV_INFO(device, "loading pm4 ucode version: %d\n", adreno_dev->pm4_fw_version); if (adreno_is_a3xx(adreno_dev)) adreno_regwrite(device, REG_CP_DEBUG, CP_DEBUG_DEFAULT); else adreno_regwrite(device, REG_CP_DEBUG, 0x02000000); adreno_regwrite(device, REG_CP_ME_RAM_WADDR, 0); for (i = 1; i < adreno_dev->pm4_fw_size; i++) adreno_regwrite(device, REG_CP_ME_RAM_DATA, adreno_dev->pm4_fw[i]); return 0; }
static uint32_t adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb, struct adreno_context *context, unsigned int flags, unsigned int *cmds, int sizedwords) { struct adreno_device *adreno_dev = ADRENO_DEVICE(rb->device); unsigned int *ringcmds; unsigned int timestamp; unsigned int total_sizedwords = sizedwords; unsigned int i; unsigned int rcmd_gpu; unsigned int context_id = KGSL_MEMSTORE_GLOBAL; unsigned int gpuaddr = rb->device->memstore.gpuaddr; if (context != NULL) { /* * if the context was not created with per context timestamp * support, we must use the global timestamp since issueibcmds * will be returning that one. */ if (context->flags & CTXT_FLAGS_PER_CONTEXT_TS) context_id = context->id; } /* reserve space to temporarily turn off protected mode * error checking if needed */ total_sizedwords += flags & KGSL_CMD_FLAGS_PMODE ? 4 : 0; total_sizedwords += !(flags & KGSL_CMD_FLAGS_NO_TS_CMP) ? 7 : 0; total_sizedwords += !(flags & KGSL_CMD_FLAGS_NOT_KERNEL_CMD) ? 2 : 0; if (adreno_is_a3xx(adreno_dev)) total_sizedwords += 7; total_sizedwords += 2; /* scratchpad ts for recovery */ if (context) { total_sizedwords += 3; /* sop timestamp */ total_sizedwords += 4; /* eop timestamp */ total_sizedwords += 3; /* global timestamp without cache * flush for non-zero context */ } else { total_sizedwords += 4; /* global timestamp for recovery*/ } ringcmds = adreno_ringbuffer_allocspace(rb, total_sizedwords); rcmd_gpu = rb->buffer_desc.gpuaddr + sizeof(uint)*(rb->wptr-total_sizedwords); if (!(flags & KGSL_CMD_FLAGS_NOT_KERNEL_CMD)) { GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_nop_packet(1)); GSL_RB_WRITE(ringcmds, rcmd_gpu, KGSL_CMD_IDENTIFIER); } if (flags & KGSL_CMD_FLAGS_PMODE) { /* disable protected mode error checking */ GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type3_packet(CP_SET_PROTECTED_MODE, 1)); GSL_RB_WRITE(ringcmds, rcmd_gpu, 0); } for (i = 0; i < sizedwords; i++) { GSL_RB_WRITE(ringcmds, rcmd_gpu, *cmds); cmds++; } if (flags & KGSL_CMD_FLAGS_PMODE) { /* re-enable protected mode error checking */ GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type3_packet(CP_SET_PROTECTED_MODE, 1)); GSL_RB_WRITE(ringcmds, rcmd_gpu, 1); } /* always increment the global timestamp. once. */ rb->timestamp[KGSL_MEMSTORE_GLOBAL]++; if (context) { if (context_id == KGSL_MEMSTORE_GLOBAL) rb->timestamp[context_id] = rb->timestamp[KGSL_MEMSTORE_GLOBAL]; else rb->timestamp[context_id]++; } timestamp = rb->timestamp[context_id]; /* scratchpad ts for recovery */ GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type0_packet(REG_CP_TIMESTAMP, 1)); GSL_RB_WRITE(ringcmds, rcmd_gpu, rb->timestamp[KGSL_MEMSTORE_GLOBAL]); if (adreno_is_a3xx(adreno_dev)) { /* * FLush HLSQ lazy updates to make sure there are no * rsources pending for indirect loads after the timestamp */ GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type3_packet(CP_EVENT_WRITE, 1)); GSL_RB_WRITE(ringcmds, rcmd_gpu, 0x07); /* HLSQ_FLUSH */ GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type3_packet(CP_WAIT_FOR_IDLE, 1)); GSL_RB_WRITE(ringcmds, rcmd_gpu, 0x00); } if (context) { /* start-of-pipeline timestamp */ GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type3_packet(CP_MEM_WRITE, 2)); GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr + KGSL_MEMSTORE_OFFSET(context->id, soptimestamp))); GSL_RB_WRITE(ringcmds, rcmd_gpu, timestamp); /* end-of-pipeline timestamp */ GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type3_packet(CP_EVENT_WRITE, 3)); GSL_RB_WRITE(ringcmds, rcmd_gpu, CACHE_FLUSH_TS); GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr + KGSL_MEMSTORE_OFFSET(context->id, eoptimestamp))); GSL_RB_WRITE(ringcmds, rcmd_gpu, timestamp); GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type3_packet(CP_MEM_WRITE, 2)); GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr + KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, eoptimestamp))); GSL_RB_WRITE(ringcmds, rcmd_gpu, rb->timestamp[KGSL_MEMSTORE_GLOBAL]); } else { GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type3_packet(CP_EVENT_WRITE, 3)); GSL_RB_WRITE(ringcmds, rcmd_gpu, CACHE_FLUSH_TS); GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr + KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, eoptimestamp))); GSL_RB_WRITE(ringcmds, rcmd_gpu, rb->timestamp[KGSL_MEMSTORE_GLOBAL]); } if (!(flags & KGSL_CMD_FLAGS_NO_TS_CMP)) { /* Conditional execution based on memory values */ GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type3_packet(CP_COND_EXEC, 4)); GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr + KGSL_MEMSTORE_OFFSET( context_id, ts_cmp_enable)) >> 2); GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr + KGSL_MEMSTORE_OFFSET( context_id, ref_wait_ts)) >> 2); GSL_RB_WRITE(ringcmds, rcmd_gpu, timestamp); /* # of conditional command DWORDs */ GSL_RB_WRITE(ringcmds, rcmd_gpu, 2); GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type3_packet(CP_INTERRUPT, 1)); GSL_RB_WRITE(ringcmds, rcmd_gpu, CP_INT_CNTL__RB_INT_MASK); }
int adreno_ringbuffer_start(struct adreno_ringbuffer *rb, unsigned int init_ram) { int status; /*cp_rb_cntl_u cp_rb_cntl; */ union reg_cp_rb_cntl cp_rb_cntl; unsigned int rb_cntl; struct kgsl_device *device = rb->device; struct adreno_device *adreno_dev = ADRENO_DEVICE(device); if (rb->flags & KGSL_FLAGS_STARTED) return 0; if (init_ram) rb->timestamp[KGSL_MEMSTORE_GLOBAL] = 0; kgsl_sharedmem_set(&rb->memptrs_desc, 0, 0, sizeof(struct kgsl_rbmemptrs)); kgsl_sharedmem_set(&rb->buffer_desc, 0, 0xAA, (rb->sizedwords << 2)); if (adreno_is_a2xx(adreno_dev)) { adreno_regwrite(device, REG_CP_RB_WPTR_BASE, (rb->memptrs_desc.gpuaddr + GSL_RB_MEMPTRS_WPTRPOLL_OFFSET)); /* setup WPTR delay */ adreno_regwrite(device, REG_CP_RB_WPTR_DELAY, 0 /*0x70000010 */); } /*setup REG_CP_RB_CNTL */ adreno_regread(device, REG_CP_RB_CNTL, &rb_cntl); cp_rb_cntl.val = rb_cntl; /* * The size of the ringbuffer in the hardware is the log2 * representation of the size in quadwords (sizedwords / 2) */ cp_rb_cntl.f.rb_bufsz = ilog2(rb->sizedwords >> 1); /* * Specify the quadwords to read before updating mem RPTR. * Like above, pass the log2 representation of the blocksize * in quadwords. */ cp_rb_cntl.f.rb_blksz = ilog2(KGSL_RB_BLKSIZE >> 3); if (adreno_is_a2xx(adreno_dev)) { /* WPTR polling */ cp_rb_cntl.f.rb_poll_en = GSL_RB_CNTL_POLL_EN; } /* mem RPTR writebacks */ cp_rb_cntl.f.rb_no_update = GSL_RB_CNTL_NO_UPDATE; adreno_regwrite(device, REG_CP_RB_CNTL, cp_rb_cntl.val); adreno_regwrite(device, REG_CP_RB_BASE, rb->buffer_desc.gpuaddr); adreno_regwrite(device, REG_CP_RB_RPTR_ADDR, rb->memptrs_desc.gpuaddr + GSL_RB_MEMPTRS_RPTR_OFFSET); if (adreno_is_a3xx(adreno_dev)) { /* enable access protection to privileged registers */ adreno_regwrite(device, A3XX_CP_PROTECT_CTRL, 0x00000007); /* RBBM registers */ adreno_regwrite(device, A3XX_CP_PROTECT_REG_0, 0x63000040); adreno_regwrite(device, A3XX_CP_PROTECT_REG_1, 0x62000080); adreno_regwrite(device, A3XX_CP_PROTECT_REG_2, 0x600000CC); adreno_regwrite(device, A3XX_CP_PROTECT_REG_3, 0x60000108); adreno_regwrite(device, A3XX_CP_PROTECT_REG_4, 0x64000140); adreno_regwrite(device, A3XX_CP_PROTECT_REG_5, 0x66000400); /* CP registers */ adreno_regwrite(device, A3XX_CP_PROTECT_REG_6, 0x65000700); adreno_regwrite(device, A3XX_CP_PROTECT_REG_7, 0x610007D8); adreno_regwrite(device, A3XX_CP_PROTECT_REG_8, 0x620007E0); adreno_regwrite(device, A3XX_CP_PROTECT_REG_9, 0x61001178); adreno_regwrite(device, A3XX_CP_PROTECT_REG_A, 0x64001180); /* RB registers */ adreno_regwrite(device, A3XX_CP_PROTECT_REG_B, 0x60003300); /* VBIF registers */ adreno_regwrite(device, A3XX_CP_PROTECT_REG_C, 0x6B00C000); } if (adreno_is_a2xx(adreno_dev)) { /* explicitly clear all cp interrupts */ adreno_regwrite(device, REG_CP_INT_ACK, 0xFFFFFFFF); } /* setup scratch/timestamp */ adreno_regwrite(device, REG_SCRATCH_ADDR, device->memstore.gpuaddr + KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, soptimestamp)); adreno_regwrite(device, REG_SCRATCH_UMSK, GSL_RB_MEMPTRS_SCRATCH_MASK); /* load the CP ucode */ status = adreno_ringbuffer_load_pm4_ucode(device); if (status != 0) return status; /* load the prefetch parser ucode */ status = adreno_ringbuffer_load_pfp_ucode(device); if (status != 0) return status; if (adreno_is_a305(adreno_dev) || adreno_is_a320(adreno_dev)) adreno_regwrite(device, REG_CP_QUEUE_THRESHOLDS, 0x000F0602); rb->rptr = 0; rb->wptr = 0; /* clear ME_HALT to start micro engine */ adreno_regwrite(device, REG_CP_ME_CNTL, 0); /* ME init is GPU specific, so jump into the sub-function */ adreno_dev->gpudev->rb_init(adreno_dev, rb); /* idle device to validate ME INIT */ status = adreno_idle(device, KGSL_TIMEOUT_DEFAULT); if (status == 0) rb->flags |= KGSL_FLAGS_STARTED; return status; }
void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, struct msm_file_private *ctx) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); struct msm_drm_private *priv = gpu->dev->dev_private; struct msm_ringbuffer *ring = gpu->rb; unsigned i; for (i = 0; i < submit->nr_cmds; i++) { switch (submit->cmd[i].type) { case MSM_SUBMIT_CMD_IB_TARGET_BUF: /* ignore IB-targets */ break; case MSM_SUBMIT_CMD_CTX_RESTORE_BUF: /* ignore if there has not been a ctx switch: */ if (priv->lastctx == ctx) break; case MSM_SUBMIT_CMD_BUF: OUT_PKT3(ring, adreno_is_a430(adreno_gpu) ? CP_INDIRECT_BUFFER_PFE : CP_INDIRECT_BUFFER_PFD, 2); OUT_RING(ring, submit->cmd[i].iova); OUT_RING(ring, submit->cmd[i].size); OUT_PKT2(ring); break; } } OUT_PKT0(ring, REG_AXXX_CP_SCRATCH_REG2, 1); OUT_RING(ring, submit->fence->seqno); if (adreno_is_a3xx(adreno_gpu) || adreno_is_a4xx(adreno_gpu)) { /* Flush HLSQ lazy updates to make sure there is nothing * pending for indirect loads after the timestamp has * passed: */ OUT_PKT3(ring, CP_EVENT_WRITE, 1); OUT_RING(ring, HLSQ_FLUSH); OUT_PKT3(ring, CP_WAIT_FOR_IDLE, 1); OUT_RING(ring, 0x00000000); } OUT_PKT3(ring, CP_EVENT_WRITE, 3); OUT_RING(ring, CACHE_FLUSH_TS); OUT_RING(ring, rbmemptr(adreno_gpu, fence)); OUT_RING(ring, submit->fence->seqno); /* we could maybe be clever and only CP_COND_EXEC the interrupt: */ OUT_PKT3(ring, CP_INTERRUPT, 1); OUT_RING(ring, 0x80000000); /* Workaround for missing irq issue on 8x16/a306. Unsure if the * root cause is a platform issue or some a306 quirk, but this * keeps things humming along: */ if (adreno_is_a306(adreno_gpu)) { OUT_PKT3(ring, CP_WAIT_FOR_IDLE, 1); OUT_RING(ring, 0x00000000); OUT_PKT3(ring, CP_INTERRUPT, 1); OUT_RING(ring, 0x80000000); } #if 0 if (adreno_is_a3xx(adreno_gpu)) { /* Dummy set-constant to trigger context rollover */ OUT_PKT3(ring, CP_SET_CONSTANT, 2); OUT_RING(ring, CP_REG(REG_A3XX_HLSQ_CL_KERNEL_GROUP_X_REG)); OUT_RING(ring, 0x00000000); } #endif gpu->funcs->flush(gpu); }
static uint32_t adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb, unsigned int flags, unsigned int *cmds, int sizedwords) { struct adreno_device *adreno_dev = ADRENO_DEVICE(rb->device); unsigned int *ringcmds; unsigned int timestamp; unsigned int total_sizedwords = sizedwords + 6; unsigned int i; unsigned int rcmd_gpu; /* reserve space to temporarily turn off protected mode * error checking if needed */ total_sizedwords += flags & KGSL_CMD_FLAGS_PMODE ? 4 : 0; total_sizedwords += !(flags & KGSL_CMD_FLAGS_NO_TS_CMP) ? 7 : 0; total_sizedwords += !(flags & KGSL_CMD_FLAGS_NOT_KERNEL_CMD) ? 2 : 0; if (adreno_is_a3xx(adreno_dev)) total_sizedwords += 7; ringcmds = adreno_ringbuffer_allocspace(rb, total_sizedwords); rcmd_gpu = rb->buffer_desc.gpuaddr + sizeof(uint)*(rb->wptr-total_sizedwords); if (!(flags & KGSL_CMD_FLAGS_NOT_KERNEL_CMD)) { GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_nop_packet(1)); GSL_RB_WRITE(ringcmds, rcmd_gpu, KGSL_CMD_IDENTIFIER); } if (flags & KGSL_CMD_FLAGS_PMODE) { /* disable protected mode error checking */ GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type3_packet(CP_SET_PROTECTED_MODE, 1)); GSL_RB_WRITE(ringcmds, rcmd_gpu, 0); } for (i = 0; i < sizedwords; i++) { GSL_RB_WRITE(ringcmds, rcmd_gpu, *cmds); cmds++; } if (flags & KGSL_CMD_FLAGS_PMODE) { /* re-enable protected mode error checking */ GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type3_packet(CP_SET_PROTECTED_MODE, 1)); GSL_RB_WRITE(ringcmds, rcmd_gpu, 1); } rb->timestamp++; timestamp = rb->timestamp; /* start-of-pipeline and end-of-pipeline timestamps */ GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type0_packet(REG_CP_TIMESTAMP, 1)); GSL_RB_WRITE(ringcmds, rcmd_gpu, rb->timestamp); if (adreno_is_a3xx(adreno_dev)) { /* * FLush HLSQ lazy updates to make sure there are no * rsources pending for indirect loads after the timestamp */ GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type3_packet(CP_EVENT_WRITE, 1)); GSL_RB_WRITE(ringcmds, rcmd_gpu, 0x07); /* HLSQ_FLUSH */ GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type3_packet(CP_WAIT_FOR_IDLE, 1)); GSL_RB_WRITE(ringcmds, rcmd_gpu, 0x00); } GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type3_packet(CP_EVENT_WRITE, 3)); GSL_RB_WRITE(ringcmds, rcmd_gpu, CACHE_FLUSH_TS); GSL_RB_WRITE(ringcmds, rcmd_gpu, (rb->device->memstore.gpuaddr + KGSL_DEVICE_MEMSTORE_OFFSET(eoptimestamp))); GSL_RB_WRITE(ringcmds, rcmd_gpu, rb->timestamp); if (!(flags & KGSL_CMD_FLAGS_NO_TS_CMP)) { /* Conditional execution based on memory values */ GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type3_packet(CP_COND_EXEC, 4)); GSL_RB_WRITE(ringcmds, rcmd_gpu, (rb->device->memstore.gpuaddr + KGSL_DEVICE_MEMSTORE_OFFSET(ts_cmp_enable)) >> 2); GSL_RB_WRITE(ringcmds, rcmd_gpu, (rb->device->memstore.gpuaddr + KGSL_DEVICE_MEMSTORE_OFFSET(ref_wait_ts)) >> 2); GSL_RB_WRITE(ringcmds, rcmd_gpu, rb->timestamp); /* # of conditional command DWORDs */ GSL_RB_WRITE(ringcmds, rcmd_gpu, 2); GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type3_packet(CP_INTERRUPT, 1)); GSL_RB_WRITE(ringcmds, rcmd_gpu, CP_INT_CNTL__RB_INT_MASK); }
static uint32_t adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb, struct adreno_context *context, unsigned int flags, unsigned int *cmds, int sizedwords) { struct adreno_device *adreno_dev = ADRENO_DEVICE(rb->device); unsigned int *ringcmds; unsigned int timestamp; unsigned int total_sizedwords = sizedwords; unsigned int i; unsigned int rcmd_gpu; unsigned int context_id = KGSL_MEMSTORE_GLOBAL; unsigned int gpuaddr = rb->device->memstore.gpuaddr; if (context->flags & CTXT_FLAGS_PER_CONTEXT_TS) context_id = context->id; total_sizedwords += flags & KGSL_CMD_FLAGS_PMODE ? 4 : 0; total_sizedwords += !(flags & KGSL_CMD_FLAGS_NO_TS_CMP) ? 7 : 0; total_sizedwords += 2; if (adreno_is_a3xx(adreno_dev)) total_sizedwords += 7; total_sizedwords += 2; if (context->flags & CTXT_FLAGS_PER_CONTEXT_TS) { total_sizedwords += 3; total_sizedwords += 4; total_sizedwords += 3; } else { total_sizedwords += 4; } ringcmds = adreno_ringbuffer_allocspace(rb, total_sizedwords); if (context->flags & CTXT_FLAGS_GPU_HANG) { KGSL_CTXT_WARN(rb->device, "Context %p caused a gpu hang. Will not accept commands for context %d\n", context, context->id); return rb->timestamp[context_id]; } rcmd_gpu = rb->buffer_desc.gpuaddr + sizeof(uint)*(rb->wptr-total_sizedwords); GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_nop_packet(1)); GSL_RB_WRITE(ringcmds, rcmd_gpu, KGSL_CMD_IDENTIFIER); if (flags & KGSL_CMD_FLAGS_PMODE) { GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type3_packet(CP_SET_PROTECTED_MODE, 1)); GSL_RB_WRITE(ringcmds, rcmd_gpu, 0); } for (i = 0; i < sizedwords; i++) { GSL_RB_WRITE(ringcmds, rcmd_gpu, *cmds); cmds++; } if (flags & KGSL_CMD_FLAGS_PMODE) { GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type3_packet(CP_SET_PROTECTED_MODE, 1)); GSL_RB_WRITE(ringcmds, rcmd_gpu, 1); } rb->timestamp[KGSL_MEMSTORE_GLOBAL]++; if (context) { if (context_id == KGSL_MEMSTORE_GLOBAL) rb->timestamp[context_id] = rb->timestamp[KGSL_MEMSTORE_GLOBAL]; else rb->timestamp[context_id]++; } timestamp = rb->timestamp[context_id]; GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type0_packet(REG_CP_TIMESTAMP, 1)); GSL_RB_WRITE(ringcmds, rcmd_gpu, rb->timestamp[KGSL_MEMSTORE_GLOBAL]); if (adreno_is_a3xx(adreno_dev)) { GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type3_packet(CP_EVENT_WRITE, 1)); GSL_RB_WRITE(ringcmds, rcmd_gpu, 0x07); GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type3_packet(CP_WAIT_FOR_IDLE, 1)); GSL_RB_WRITE(ringcmds, rcmd_gpu, 0x00); } if (context->flags & CTXT_FLAGS_PER_CONTEXT_TS) { GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type3_packet(CP_MEM_WRITE, 2)); GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr + KGSL_MEMSTORE_OFFSET(context->id, soptimestamp))); GSL_RB_WRITE(ringcmds, rcmd_gpu, timestamp); GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type3_packet(CP_EVENT_WRITE, 3)); GSL_RB_WRITE(ringcmds, rcmd_gpu, CACHE_FLUSH_TS); GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr + KGSL_MEMSTORE_OFFSET(context->id, eoptimestamp))); GSL_RB_WRITE(ringcmds, rcmd_gpu, timestamp); GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type3_packet(CP_MEM_WRITE, 2)); GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr + KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, eoptimestamp))); GSL_RB_WRITE(ringcmds, rcmd_gpu, rb->timestamp[KGSL_MEMSTORE_GLOBAL]); } else { GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type3_packet(CP_EVENT_WRITE, 3)); GSL_RB_WRITE(ringcmds, rcmd_gpu, CACHE_FLUSH_TS); GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr + KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, eoptimestamp))); GSL_RB_WRITE(ringcmds, rcmd_gpu, rb->timestamp[KGSL_MEMSTORE_GLOBAL]); } if (!(flags & KGSL_CMD_FLAGS_NO_TS_CMP)) { GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type3_packet(CP_COND_EXEC, 4)); GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr + KGSL_MEMSTORE_OFFSET( context_id, ts_cmp_enable)) >> 2); GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr + KGSL_MEMSTORE_OFFSET( context_id, ref_wait_ts)) >> 2); GSL_RB_WRITE(ringcmds, rcmd_gpu, timestamp); GSL_RB_WRITE(ringcmds, rcmd_gpu, 2); GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type3_packet(CP_INTERRUPT, 1)); GSL_RB_WRITE(ringcmds, rcmd_gpu, CP_INT_CNTL__RB_INT_MASK); }
int adreno_ringbuffer_start(struct adreno_ringbuffer *rb, unsigned int init_ram) { int status; union reg_cp_rb_cntl cp_rb_cntl; unsigned int rb_cntl; struct kgsl_device *device = rb->device; struct adreno_device *adreno_dev = ADRENO_DEVICE(device); if (rb->flags & KGSL_FLAGS_STARTED) return 0; if (init_ram) rb->timestamp[KGSL_MEMSTORE_GLOBAL] = 0; kgsl_sharedmem_set(&rb->memptrs_desc, 0, 0, sizeof(struct kgsl_rbmemptrs)); kgsl_sharedmem_set(&rb->buffer_desc, 0, 0xAA, (rb->sizedwords << 2)); if (adreno_is_a2xx(adreno_dev)) { adreno_regwrite(device, REG_CP_RB_WPTR_BASE, (rb->memptrs_desc.gpuaddr + GSL_RB_MEMPTRS_WPTRPOLL_OFFSET)); adreno_regwrite(device, REG_CP_RB_WPTR_DELAY, 0 ); } adreno_regread(device, REG_CP_RB_CNTL, &rb_cntl); cp_rb_cntl.val = rb_cntl; cp_rb_cntl.f.rb_bufsz = ilog2(rb->sizedwords >> 1); cp_rb_cntl.f.rb_blksz = ilog2(KGSL_RB_BLKSIZE >> 3); if (adreno_is_a2xx(adreno_dev)) { cp_rb_cntl.f.rb_poll_en = GSL_RB_CNTL_POLL_EN; } cp_rb_cntl.f.rb_no_update = GSL_RB_CNTL_NO_UPDATE; adreno_regwrite(device, REG_CP_RB_CNTL, cp_rb_cntl.val); adreno_regwrite(device, REG_CP_RB_BASE, rb->buffer_desc.gpuaddr); adreno_regwrite(device, REG_CP_RB_RPTR_ADDR, rb->memptrs_desc.gpuaddr + GSL_RB_MEMPTRS_RPTR_OFFSET); if (adreno_is_a3xx(adreno_dev)) { adreno_regwrite(device, A3XX_CP_PROTECT_CTRL, 0x00000007); adreno_regwrite(device, A3XX_CP_PROTECT_REG_0, 0x63000040); adreno_regwrite(device, A3XX_CP_PROTECT_REG_1, 0x62000080); adreno_regwrite(device, A3XX_CP_PROTECT_REG_2, 0x600000CC); adreno_regwrite(device, A3XX_CP_PROTECT_REG_3, 0x60000108); adreno_regwrite(device, A3XX_CP_PROTECT_REG_4, 0x64000140); adreno_regwrite(device, A3XX_CP_PROTECT_REG_5, 0x66000400); adreno_regwrite(device, A3XX_CP_PROTECT_REG_6, 0x65000700); adreno_regwrite(device, A3XX_CP_PROTECT_REG_7, 0x610007D8); adreno_regwrite(device, A3XX_CP_PROTECT_REG_8, 0x620007E0); adreno_regwrite(device, A3XX_CP_PROTECT_REG_9, 0x61001178); adreno_regwrite(device, A3XX_CP_PROTECT_REG_A, 0x64001180); adreno_regwrite(device, A3XX_CP_PROTECT_REG_B, 0x60003300); adreno_regwrite(device, A3XX_CP_PROTECT_REG_C, 0x6B00C000); } if (adreno_is_a2xx(adreno_dev)) { adreno_regwrite(device, REG_CP_INT_ACK, 0xFFFFFFFF); } adreno_regwrite(device, REG_SCRATCH_ADDR, device->memstore.gpuaddr + KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, soptimestamp)); adreno_regwrite(device, REG_SCRATCH_UMSK, GSL_RB_MEMPTRS_SCRATCH_MASK); status = adreno_ringbuffer_load_pm4_ucode(device); if (status != 0) return status; status = adreno_ringbuffer_load_pfp_ucode(device); if (status != 0) return status; if (adreno_is_a305(adreno_dev) || adreno_is_a320(adreno_dev)) adreno_regwrite(device, REG_CP_QUEUE_THRESHOLDS, 0x000E0602); rb->rptr = 0; rb->wptr = 0; adreno_regwrite(device, REG_CP_ME_CNTL, 0); adreno_dev->gpudev->rb_init(adreno_dev, rb); status = adreno_idle(device, KGSL_TIMEOUT_DEFAULT); if (status == 0) rb->flags |= KGSL_FLAGS_STARTED; return status; }