static int kgsl_ringbuffer_load_pm4_ucode(struct kgsl_device *device) { int status = 0; int i; const struct firmware *fw = NULL; unsigned int *fw_ptr = NULL; size_t fw_word_size = 0; status = request_firmware(&fw, YAMATO_PM4_FW, kgsl_driver.base_dev[KGSL_DEVICE_YAMATO]); if (status != 0) { KGSL_DRV_ERR("request_firmware failed for %s with error %d\n", YAMATO_PM4_FW, status); goto done; } if ((fw->size % (sizeof(uint32_t)*3)) != 4) { KGSL_DRV_ERR("bad firmware size %d.\n", fw->size); status = -EINVAL; goto done; } fw_ptr = (unsigned int *)fw->data; fw_word_size = fw->size/sizeof(uint32_t); KGSL_DRV_INFO("loading pm4 ucode version: %d\n", fw_ptr[0]); kgsl_yamato_regwrite(device, REG_CP_DEBUG, 0x02000000); kgsl_yamato_regwrite(device, REG_CP_ME_RAM_WADDR, 0); for (i = 1; i < fw_word_size; i++) kgsl_yamato_regwrite(device, REG_CP_ME_RAM_DATA, fw_ptr[i]); done: release_firmware(fw); return status; }
static int kgsl_ringbuffer_load_pfp_ucode(struct kgsl_device *device) { int status = 0; int i; const struct firmware *fw = NULL; unsigned int *fw_ptr = NULL; size_t fw_word_size = 0; status = request_firmware(&fw, YAMATO_PFP_FW, kgsl_driver.base_dev[KGSL_DEVICE_YAMATO]); if (status != 0) { KGSL_DRV_ERR("request_firmware for %s failed with error %d\n", YAMATO_PFP_FW, status); return status; } if ((fw->size % sizeof(uint32_t)) != 0) { KGSL_DRV_ERR("bad firmware size %d.\n", fw->size); release_firmware(fw); return -EINVAL; } fw_ptr = (unsigned int *)fw->data; fw_word_size = fw->size/sizeof(uint32_t); KGSL_DRV_INFO("loading pfp ucode version: %d\n", fw_ptr[0]); kgsl_yamato_regwrite(device, REG_CP_PFP_UCODE_ADDR, 0); for (i = 1; i < fw_word_size; i++) kgsl_yamato_regwrite(device, REG_CP_PFP_UCODE_DATA, fw_ptr[i]); release_firmware(fw); return status; }
int kgsl_ringbuffer_stop(struct kgsl_ringbuffer *rb) { if (rb->flags & KGSL_FLAGS_STARTED) { kgsl_yamato_regwrite(rb->device, REG_CP_INT_CNTL, 0); /* ME_HALT */ kgsl_yamato_regwrite(rb->device, REG_CP_ME_CNTL, 0x10000000); rb->flags &= ~KGSL_FLAGS_STARTED; } return 0; }
static int kgsl_ringbuffer_load_pm4_ucode(struct kgsl_device *device) { int status = 0; int i; const struct firmware *fw = NULL; unsigned int *fw_ptr = NULL; size_t fw_word_size = 0; if (device->chip_id == KGSL_CHIPID_LEIA_REV470) { status = request_firmware(&fw, LEIA_PM4_470_FW, kgsl_driver.base_dev[KGSL_DEVICE_YAMATO]); if (status != 0) { KGSL_DRV_ERR( "request_firmware failed for %s \ with error %d\n", LEIA_PM4_470_FW, status); goto error; } } else { status = request_firmware(&fw, YAMATO_PM4_FW, kgsl_driver.base_dev[KGSL_DEVICE_YAMATO]); if (status != 0) { KGSL_DRV_ERR( "request_firmware failed for %s \ with error %d\n", YAMATO_PM4_FW, status); goto error; } } /*this firmware must come in 3 word chunks. plus 1 word of version*/ if ((fw->size % (sizeof(uint32_t)*3)) != 4) { KGSL_DRV_ERR("bad firmware size %d.\n", fw->size); status = -EINVAL; goto error_release_fw; } fw_ptr = (unsigned int *)fw->data; fw_word_size = fw->size/sizeof(uint32_t); KGSL_DRV_INFO("loading pm4 ucode version: %d\n", fw_ptr[0]); kgsl_yamato_regwrite(device, REG_CP_DEBUG, 0x02000000); kgsl_yamato_regwrite(device, REG_CP_ME_RAM_WADDR, 0); for (i = 1; i < fw_word_size; i++) kgsl_yamato_regwrite(device, REG_CP_ME_RAM_DATA, fw_ptr[i]); error_release_fw: release_firmware(fw); error: return status; }
void kgsl_ringbuffer_stop(struct kgsl_ringbuffer *rb) { KGSL_CMD_VDBG("enter (rb=%p)\n", rb); if (rb->flags & KGSL_FLAGS_STARTED) { KGSL_CMD_DBG("disabling CP interrupts: mask %08x\n", 0); kgsl_yamato_regwrite(rb->device, REG_CP_INT_CNTL, 0); /* ME_HALT */ kgsl_yamato_regwrite(rb->device, REG_CP_ME_CNTL, 0x10000000); rb->flags &= ~KGSL_FLAGS_STARTED; } KGSL_CMD_VDBG("return %d\n", 0); }
static int kgsl_ringbuffer_load_pm4_ucode(struct kgsl_device *device) { struct kgsl_yamato_device *yamato_device = KGSL_YAMATO_DEVICE(device); const char *fwfile; int i, ret = 0; if (device->chip_id == KGSL_CHIPID_LEIA_REV470) fwfile = LEIA_PM4_470_FW; else fwfile = YAMATO_PM4_FW; if (yamato_device->pm4_fw == NULL) { int len; unsigned int *ptr; ret = _load_firmware(device, fwfile, (void *) &ptr, &len); if (ret) goto err; /* PM4 size is 3 dword aligned plus 1 dword of version */ if (len % ((sizeof(uint32_t) * 3)) != sizeof(uint32_t)) { KGSL_DRV_ERR(device, "Bad firmware size: %d\n", len); ret = -EINVAL; goto err; } yamato_device->pm4_fw_size = len / sizeof(uint32_t); yamato_device->pm4_fw = ptr; } KGSL_DRV_INFO(device, "loading pm4 ucode version: %d\n", yamato_device->pm4_fw[0]); kgsl_yamato_regwrite(device, REG_CP_DEBUG, 0x02000000); kgsl_yamato_regwrite(device, REG_CP_ME_RAM_WADDR, 0); for (i = 1; i < yamato_device->pm4_fw_size; i++) kgsl_yamato_regwrite(device, REG_CP_ME_RAM_DATA, yamato_device->pm4_fw[i]); err: return ret; }
static int kgsl_ringbuffer_load_pfp_ucode(struct kgsl_device *device) { struct kgsl_yamato_device *yamato_device = KGSL_YAMATO_DEVICE(device); const char *fwfile; int i, ret = 0; if (device->chip_id == KGSL_CHIPID_LEIA_REV470) fwfile = LEIA_PFP_470_FW; else fwfile = YAMATO_PFP_FW; if (yamato_device->pfp_fw == NULL) { int len; unsigned int *ptr; ret = _load_firmware(device, fwfile, (void *) &ptr, &len); if (ret) goto err; /* PFP size shold be dword aligned */ if (len % sizeof(uint32_t) != 0) { KGSL_DRV_ERR(device, "Bad firmware size: %d\n", len); ret = -EINVAL; goto err; } yamato_device->pfp_fw_size = len / sizeof(uint32_t); yamato_device->pfp_fw = ptr; } KGSL_DRV_INFO(device, "loading pfp ucode version: %d\n", yamato_device->pfp_fw[0]); kgsl_yamato_regwrite(device, REG_CP_PFP_UCODE_ADDR, 0); for (i = 1; i < yamato_device->pfp_fw_size; i++) kgsl_yamato_regwrite(device, REG_CP_PFP_UCODE_DATA, yamato_device->pfp_fw[i]); err: return ret; }
static void kgsl_ringbuffer_submit(struct kgsl_ringbuffer *rb) { BUG_ON(rb->wptr == 0); /*synchronize memory before informing the hardware of the *new commands. */ mb(); kgsl_yamato_regwrite(rb->device, REG_CP_RB_WPTR, rb->wptr); rb->flags |= KGSL_FLAGS_ACTIVE; }
static void kgsl_ringbuffer_submit(struct kgsl_ringbuffer *rb) { BUG_ON(rb->wptr == 0); GSL_RB_UPDATE_WPTR_POLLING(rb); dsb(); wmb(); mb(); kgsl_yamato_regwrite(rb->device, REG_CP_RB_WPTR, rb->wptr); rb->flags |= KGSL_FLAGS_ACTIVE; }
static void kgsl_ringbuffer_submit(struct kgsl_ringbuffer *rb) { BUG_ON(rb->wptr == 0); GSL_RB_UPDATE_WPTR_POLLING(rb); /* Drain write buffer and data memory barrier */ dsb(); wmb(); /* Memory fence to ensure all data has posted. On some systems, * like 7x27, the register block is not allocated as strongly ordered * memory. Adding a memory fence ensures ordering during ringbuffer * submits.*/ mb(); kgsl_yamato_regwrite(rb->device, REG_CP_RB_WPTR, rb->wptr); rb->flags |= KGSL_FLAGS_ACTIVE; }
void kgsl_mh_intrcallback(struct kgsl_device *device) { unsigned int status = 0; unsigned int reg; unsigned int axi_error; struct kgsl_mmu_debug dbg; KGSL_MEM_VDBG("enter (device=%p)\n", device); kgsl_yamato_regread(device, REG_MH_INTERRUPT_STATUS, &status); if (status & MH_INTERRUPT_MASK__AXI_READ_ERROR) { kgsl_yamato_regread(device, REG_MH_AXI_ERROR, &axi_error); KGSL_MEM_FATAL("axi read error interrupt (%08x)\n", axi_error); kgsl_mmu_debug(&device->mmu, &dbg); } else if (status & MH_INTERRUPT_MASK__AXI_WRITE_ERROR) { kgsl_yamato_regread(device, REG_MH_AXI_ERROR, &axi_error); KGSL_MEM_FATAL("axi write error interrupt (%08x)\n", axi_error); kgsl_mmu_debug(&device->mmu, &dbg); } else if (status & MH_INTERRUPT_MASK__MMU_PAGE_FAULT) { kgsl_yamato_regread(device, REG_MH_MMU_PAGE_FAULT, ®); KGSL_MEM_FATAL("mmu page fault interrupt: %08x\n", reg); kgsl_mmu_debug(&device->mmu, &dbg); } else { KGSL_MEM_DBG("bad bits in REG_MH_INTERRUPT_STATUS %08x\n", status); } kgsl_yamato_regwrite(device, REG_MH_INTERRUPT_CLEAR, status); /*TODO: figure out how to handle errror interupts. * specifically, page faults should probably nuke the client that * caused them, but we don't have enough info to figure that out yet. */ KGSL_MEM_VDBG("return\n"); }
static int kgsl_ringbuffer_start(struct kgsl_ringbuffer *rb) { int status; union reg_cp_rb_cntl cp_rb_cntl; unsigned int *cmds, rb_cntl; struct kgsl_device *device = rb->device; KGSL_CMD_VDBG("enter (rb=%p)\n", rb); if (rb->flags & KGSL_FLAGS_STARTED) { KGSL_CMD_VDBG("return %d\n", 0); return 0; } kgsl_sharedmem_set(&rb->memptrs_desc, 0, 0, sizeof(struct kgsl_rbmemptrs)); kgsl_sharedmem_set(&rb->buffer_desc, 0, 0xAA, (rb->sizedwords << 2)); kgsl_yamato_regwrite(device, REG_CP_RB_WPTR_BASE, (rb->memptrs_desc.gpuaddr + GSL_RB_MEMPTRS_WPTRPOLL_OFFSET)); kgsl_yamato_regwrite(device, REG_CP_RB_WPTR_DELAY, 0 ); kgsl_yamato_regread(device, REG_CP_RB_CNTL, &rb_cntl); cp_rb_cntl.val = rb_cntl; cp_rb_cntl.f.rb_bufsz = kgsl_ringbuffer_sizelog2quadwords(rb->sizedwords); cp_rb_cntl.f.rb_blksz = rb->blksizequadwords; cp_rb_cntl.f.rb_poll_en = GSL_RB_CNTL_POLL_EN; cp_rb_cntl.f.rb_no_update = GSL_RB_CNTL_NO_UPDATE; kgsl_yamato_regwrite(device, REG_CP_RB_CNTL, cp_rb_cntl.val); kgsl_yamato_regwrite(device, REG_CP_RB_BASE, rb->buffer_desc.gpuaddr); kgsl_yamato_regwrite(device, REG_CP_RB_RPTR_ADDR, rb->memptrs_desc.gpuaddr + GSL_RB_MEMPTRS_RPTR_OFFSET); kgsl_yamato_regwrite(device, REG_CP_INT_ACK, 0xFFFFFFFF); kgsl_yamato_regwrite(device, REG_SCRATCH_ADDR, device->memstore.gpuaddr + KGSL_DEVICE_MEMSTORE_OFFSET(soptimestamp)); kgsl_yamato_regwrite(device, REG_SCRATCH_UMSK, GSL_RB_MEMPTRS_SCRATCH_MASK); status = kgsl_ringbuffer_load_pm4_ucode(device); if (status != 0) { KGSL_DRV_ERR("kgsl_ringbuffer_load_pm4_ucode failed %d\n", status); return status; } status = kgsl_ringbuffer_load_pfp_ucode(device); if (status != 0) { KGSL_DRV_ERR("kgsl_ringbuffer_load_pm4_ucode failed %d\n", status); return status; } kgsl_yamato_regwrite(device, REG_CP_QUEUE_THRESHOLDS, 0x000C0804); rb->rptr = 0; rb->wptr = 0; rb->timestamp = 0; GSL_RB_INIT_TIMESTAMP(rb); INIT_LIST_HEAD(&rb->memqueue); kgsl_yamato_regwrite(device, REG_CP_ME_CNTL, 0); cmds = kgsl_ringbuffer_allocspace(rb, 19); GSL_RB_WRITE(cmds, PM4_HDR_ME_INIT); GSL_RB_WRITE(cmds, 0x000003ff); GSL_RB_WRITE(cmds, 0x00000000); GSL_RB_WRITE(cmds, 0x00000000); GSL_RB_WRITE(cmds, GSL_HAL_SUBBLOCK_OFFSET(REG_RB_SURFACE_INFO)); GSL_RB_WRITE(cmds, GSL_HAL_SUBBLOCK_OFFSET(REG_PA_SC_WINDOW_OFFSET)); GSL_RB_WRITE(cmds, GSL_HAL_SUBBLOCK_OFFSET(REG_VGT_MAX_VTX_INDX)); GSL_RB_WRITE(cmds, GSL_HAL_SUBBLOCK_OFFSET(REG_SQ_PROGRAM_CNTL)); GSL_RB_WRITE(cmds, GSL_HAL_SUBBLOCK_OFFSET(REG_RB_DEPTHCONTROL)); GSL_RB_WRITE(cmds, GSL_HAL_SUBBLOCK_OFFSET(REG_PA_SU_POINT_SIZE)); GSL_RB_WRITE(cmds, GSL_HAL_SUBBLOCK_OFFSET(REG_PA_SC_LINE_CNTL)); GSL_RB_WRITE(cmds, GSL_HAL_SUBBLOCK_OFFSET(REG_PA_SU_POLY_OFFSET_FRONT_SCALE)); GSL_RB_WRITE(cmds, 0x80000180); GSL_RB_WRITE(cmds, 0x00000001); GSL_RB_WRITE(cmds, 0x00000000); GSL_RB_WRITE(cmds, 0x00000000); GSL_RB_WRITE(cmds, GSL_RB_PROTECTED_MODE_CONTROL); GSL_RB_WRITE(cmds, 0x00000000); GSL_RB_WRITE(cmds, 0x00000000); kgsl_ringbuffer_submit(rb); status = kgsl_yamato_idle(device, KGSL_TIMEOUT_DEFAULT); KGSL_CMD_DBG("enabling CP interrupts: mask %08lx\n", GSL_CP_INT_MASK); kgsl_yamato_regwrite(rb->device, REG_CP_INT_CNTL, GSL_CP_INT_MASK); if (status == 0) rb->flags |= KGSL_FLAGS_STARTED; KGSL_CMD_VDBG("return %d\n", status); return status; }
int kgsl_ringbuffer_start(struct kgsl_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 *cmds, rb_cntl; struct kgsl_device *device = rb->device; uint cmds_gpu; if (rb->flags & KGSL_FLAGS_STARTED) return 0; if (init_ram) { rb->timestamp = 0; GSL_RB_INIT_TIMESTAMP(rb); } kgsl_sharedmem_set(&rb->memptrs_desc, 0, 0, sizeof(struct kgsl_rbmemptrs)); kgsl_sharedmem_set(&rb->buffer_desc, 0, 0xAA, (rb->sizedwords << 2)); kgsl_yamato_regwrite(device, REG_CP_RB_WPTR_BASE, (rb->memptrs_desc.gpuaddr + GSL_RB_MEMPTRS_WPTRPOLL_OFFSET)); /* setup WPTR delay */ kgsl_yamato_regwrite(device, REG_CP_RB_WPTR_DELAY, 0 /*0x70000010 */); /*setup REG_CP_RB_CNTL */ kgsl_yamato_regread(device, REG_CP_RB_CNTL, &rb_cntl); cp_rb_cntl.val = rb_cntl; /* size of ringbuffer */ cp_rb_cntl.f.rb_bufsz = kgsl_ringbuffer_sizelog2quadwords(rb->sizedwords); /* quadwords to read before updating mem RPTR */ cp_rb_cntl.f.rb_blksz = rb->blksizequadwords; cp_rb_cntl.f.rb_poll_en = GSL_RB_CNTL_POLL_EN; /* WPTR polling */ /* mem RPTR writebacks */ cp_rb_cntl.f.rb_no_update = GSL_RB_CNTL_NO_UPDATE; kgsl_yamato_regwrite(device, REG_CP_RB_CNTL, cp_rb_cntl.val); kgsl_yamato_regwrite(device, REG_CP_RB_BASE, rb->buffer_desc.gpuaddr); kgsl_yamato_regwrite(device, REG_CP_RB_RPTR_ADDR, rb->memptrs_desc.gpuaddr + GSL_RB_MEMPTRS_RPTR_OFFSET); /* explicitly clear all cp interrupts */ kgsl_yamato_regwrite(device, REG_CP_INT_ACK, 0xFFFFFFFF); /* setup scratch/timestamp */ kgsl_yamato_regwrite(device, REG_SCRATCH_ADDR, device->memstore.gpuaddr + KGSL_DEVICE_MEMSTORE_OFFSET(soptimestamp)); kgsl_yamato_regwrite(device, REG_SCRATCH_UMSK, GSL_RB_MEMPTRS_SCRATCH_MASK); /* load the CP ucode */ status = kgsl_ringbuffer_load_pm4_ucode(device); if (status != 0) return status; /* load the prefetch parser ucode */ status = kgsl_ringbuffer_load_pfp_ucode(device); if (status != 0) return status; kgsl_yamato_regwrite(device, REG_CP_QUEUE_THRESHOLDS, 0x000C0804); rb->rptr = 0; rb->wptr = 0; /* clear ME_HALT to start micro engine */ kgsl_yamato_regwrite(device, REG_CP_ME_CNTL, 0); /* ME_INIT */ cmds = kgsl_ringbuffer_allocspace(rb, 19); cmds_gpu = rb->buffer_desc.gpuaddr + sizeof(uint)*(rb->wptr-19); GSL_RB_WRITE(cmds, cmds_gpu, PM4_HDR_ME_INIT); /* All fields present (bits 9:0) */ GSL_RB_WRITE(cmds, cmds_gpu, 0x000003ff); /* Disable/Enable Real-Time Stream processing (present but ignored) */ GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000); /* Enable (2D <-> 3D) implicit synchronization (present but ignored) */ GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000); GSL_RB_WRITE(cmds, cmds_gpu, GSL_HAL_SUBBLOCK_OFFSET(REG_RB_SURFACE_INFO)); GSL_RB_WRITE(cmds, cmds_gpu, GSL_HAL_SUBBLOCK_OFFSET(REG_PA_SC_WINDOW_OFFSET)); GSL_RB_WRITE(cmds, cmds_gpu, GSL_HAL_SUBBLOCK_OFFSET(REG_VGT_MAX_VTX_INDX)); GSL_RB_WRITE(cmds, cmds_gpu, GSL_HAL_SUBBLOCK_OFFSET(REG_SQ_PROGRAM_CNTL)); GSL_RB_WRITE(cmds, cmds_gpu, GSL_HAL_SUBBLOCK_OFFSET(REG_RB_DEPTHCONTROL)); GSL_RB_WRITE(cmds, cmds_gpu, GSL_HAL_SUBBLOCK_OFFSET(REG_PA_SU_POINT_SIZE)); GSL_RB_WRITE(cmds, cmds_gpu, GSL_HAL_SUBBLOCK_OFFSET(REG_PA_SC_LINE_CNTL)); GSL_RB_WRITE(cmds, cmds_gpu, GSL_HAL_SUBBLOCK_OFFSET(REG_PA_SU_POLY_OFFSET_FRONT_SCALE)); /* Vertex and Pixel Shader Start Addresses in instructions * (3 DWORDS per instruction) */ GSL_RB_WRITE(cmds, cmds_gpu, 0x80000180); /* Maximum Contexts */ GSL_RB_WRITE(cmds, cmds_gpu, 0x00000001); /* Write Confirm Interval and The CP will wait the * wait_interval * 16 clocks between polling */ GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000); /* NQ and External Memory Swap */ GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000); /* Protected mode error checking */ GSL_RB_WRITE(cmds, cmds_gpu, GSL_RB_PROTECTED_MODE_CONTROL); /* Disable header dumping and Header dump address */ GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000); /* Header dump size */ GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000); kgsl_ringbuffer_submit(rb); /* idle device to validate ME INIT */ status = kgsl_yamato_idle(device, KGSL_TIMEOUT_DEFAULT); kgsl_yamato_regwrite(rb->device, REG_CP_INT_CNTL, GSL_CP_INT_MASK); if (status == 0) rb->flags |= KGSL_FLAGS_STARTED; return status; }
/* functions */ void kgsl_cp_intrcallback(struct kgsl_device *device) { unsigned int status = 0; struct kgsl_ringbuffer *rb = &device->ringbuffer; KGSL_CMD_VDBG("enter (device=%p)\n", device); kgsl_yamato_regread(device, REG_CP_INT_STATUS, &status); if (status & CP_INT_CNTL__RB_INT_MASK) { /* signal intr completion event */ int init_reftimestamp = 0x7fffffff; int enableflag = 0; kgsl_sharedmem_write(&rb->device->memstore, KGSL_DEVICE_MEMSTORE_OFFSET(ts_cmp_enable), &enableflag, 4); kgsl_sharedmem_write(&rb->device->memstore, KGSL_DEVICE_MEMSTORE_OFFSET(ref_wait_ts), &init_reftimestamp, 4); KGSL_CMD_WARN("ringbuffer rb interrupt\n"); } if (status & (CP_INT_CNTL__IB1_INT_MASK | CP_INT_CNTL__RB_INT_MASK)) { KGSL_CMD_WARN("ringbuffer ib1/rb interrupt\n"); wake_up_interruptible_all(&device->ib1_wq); } if (status & CP_INT_CNTL__T0_PACKET_IN_IB_MASK) { KGSL_CMD_FATAL("ringbuffer TO packet in IB interrupt\n"); kgsl_yamato_regwrite(rb->device, REG_CP_INT_CNTL, 0); kgsl_ringbuffer_dump(rb); } if (status & CP_INT_CNTL__OPCODE_ERROR_MASK) { KGSL_CMD_FATAL("ringbuffer opcode error interrupt\n"); kgsl_yamato_regwrite(rb->device, REG_CP_INT_CNTL, 0); kgsl_ringbuffer_dump(rb); } if (status & CP_INT_CNTL__PROTECTED_MODE_ERROR_MASK) { KGSL_CMD_FATAL("ringbuffer protected mode error interrupt\n"); kgsl_yamato_regwrite(rb->device, REG_CP_INT_CNTL, 0); kgsl_ringbuffer_dump(rb); } if (status & CP_INT_CNTL__RESERVED_BIT_ERROR_MASK) { KGSL_CMD_FATAL("ringbuffer reserved bit error interrupt\n"); kgsl_yamato_regwrite(rb->device, REG_CP_INT_CNTL, 0); kgsl_ringbuffer_dump(rb); } if (status & CP_INT_CNTL__IB_ERROR_MASK) { KGSL_CMD_FATAL("ringbuffer IB error interrupt\n"); kgsl_yamato_regwrite(rb->device, REG_CP_INT_CNTL, 0); kgsl_ringbuffer_dump(rb); } if (status & CP_INT_CNTL__SW_INT_MASK) KGSL_CMD_DBG("ringbuffer software interrupt\n"); if (status & CP_INT_CNTL__IB2_INT_MASK) KGSL_CMD_DBG("ringbuffer ib2 interrupt\n"); if (status & (~GSL_CP_INT_MASK)) KGSL_CMD_DBG("bad bits in REG_CP_INT_STATUS %08x\n", status); /* only ack bits we understand */ status &= GSL_CP_INT_MASK; kgsl_yamato_regwrite(device, REG_CP_INT_ACK, status); KGSL_CMD_VDBG("return\n"); }
/* functions */ void kgsl_cp_intrcallback(struct kgsl_device *device) { unsigned int status = 0, num_reads = 0, master_status = 0; struct kgsl_yamato_device *yamato_device = KGSL_YAMATO_DEVICE(device); struct kgsl_ringbuffer *rb = &yamato_device->ringbuffer; KGSL_CMD_VDBG("enter (device=%p)\n", device); kgsl_yamato_regread(device, REG_MASTER_INT_SIGNAL, &master_status); while (!status && (num_reads < VALID_STATUS_COUNT_MAX) && (master_status & MASTER_INT_SIGNAL__CP_INT_STAT)) { kgsl_yamato_regread(device, REG_CP_INT_STATUS, &status); kgsl_yamato_regread(device, REG_MASTER_INT_SIGNAL, &master_status); num_reads++; } if (num_reads > 1) KGSL_DRV_WARN("Looped %d times to read REG_CP_INT_STATUS\n", num_reads); if (!status) { if (master_status & MASTER_INT_SIGNAL__CP_INT_STAT) { /* This indicates that we could not read CP_INT_STAT. * As a precaution just wake up processes so * they can check their timestamps. Since, we * did not ack any interrupts this interrupt will * be generated again */ KGSL_DRV_WARN("Unable to read CP_INT_STATUS\n"); wake_up_interruptible_all(&yamato_device->ib1_wq); } else KGSL_DRV_WARN("Spurious interrput detected\n"); return; } if (status & CP_INT_CNTL__RB_INT_MASK) { /* signal intr completion event */ unsigned int enableflag = 0; kgsl_sharedmem_writel(&rb->device->memstore, KGSL_DEVICE_MEMSTORE_OFFSET(ts_cmp_enable), enableflag); wmb(); KGSL_CMD_WARN("ringbuffer rb interrupt\n"); } if (status & CP_INT_CNTL__T0_PACKET_IN_IB_MASK) { KGSL_CMD_FATAL("ringbuffer TO packet in IB interrupt\n"); kgsl_yamato_regwrite(rb->device, REG_CP_INT_CNTL, 0); } if (status & CP_INT_CNTL__OPCODE_ERROR_MASK) { KGSL_CMD_FATAL("ringbuffer opcode error interrupt\n"); kgsl_yamato_regwrite(rb->device, REG_CP_INT_CNTL, 0); } if (status & CP_INT_CNTL__PROTECTED_MODE_ERROR_MASK) { KGSL_CMD_FATAL("ringbuffer protected mode error interrupt\n"); kgsl_yamato_regwrite(rb->device, REG_CP_INT_CNTL, 0); } if (status & CP_INT_CNTL__RESERVED_BIT_ERROR_MASK) { KGSL_CMD_FATAL("ringbuffer reserved bit error interrupt\n"); kgsl_yamato_regwrite(rb->device, REG_CP_INT_CNTL, 0); } if (status & CP_INT_CNTL__IB_ERROR_MASK) { KGSL_CMD_FATAL("ringbuffer IB error interrupt\n"); kgsl_yamato_regwrite(rb->device, REG_CP_INT_CNTL, 0); } if (status & CP_INT_CNTL__SW_INT_MASK) KGSL_CMD_DBG("ringbuffer software interrupt\n"); if (status & CP_INT_CNTL__IB2_INT_MASK) KGSL_CMD_DBG("ringbuffer ib2 interrupt\n"); if (status & (~GSL_CP_INT_MASK)) KGSL_CMD_DBG("bad bits in REG_CP_INT_STATUS %08x\n", status); /* only ack bits we understand */ status &= GSL_CP_INT_MASK; kgsl_yamato_regwrite(device, REG_CP_INT_ACK, status); if (status & (CP_INT_CNTL__IB1_INT_MASK | CP_INT_CNTL__RB_INT_MASK)) { KGSL_CMD_WARN("ringbuffer ib1/rb interrupt\n"); wake_up_interruptible_all(&yamato_device->ib1_wq); atomic_notifier_call_chain(&(device->ts_notifier_list), KGSL_DEVICE_YAMATO, NULL); } KGSL_CMD_VDBG("return\n"); }
static int kgsl_ringbuffer_load_pfp_ucode(struct kgsl_device *device) { int status = 0; int i; const struct firmware *fw = NULL; unsigned int *fw_ptr = NULL; size_t fw_word_size = 0; struct kgsl_yamato_device *yamato_device = KGSL_YAMATO_DEVICE(device); if (yamato_device->pfp_fw == NULL) { if (device->chip_id == KGSL_CHIPID_LEIA_REV470) { status = request_firmware(&fw, LEIA_PFP_470_FW, device->dev); if (status != 0) { KGSL_DRV_ERR("request_firmware for %s \ failed with error %d\n", LEIA_PFP_470_FW, status); return status; } } else { status = request_firmware(&fw, YAMATO_PFP_FW, device->dev); if (status != 0) { KGSL_DRV_ERR("request_firmware for %s \ failed with error %d\n", YAMATO_PFP_FW, status); return status; } } /*this firmware must come in 1 word chunks. */ if ((fw->size % sizeof(uint32_t)) != 0) { KGSL_DRV_ERR("bad firmware size %d.\n", fw->size); status = -EINVAL; goto error_release_fw; } fw_ptr = (unsigned int *)fw->data; fw_word_size = fw->size/sizeof(uint32_t); yamato_device->pfp_fw_size = fw_word_size; /* keep a copy of fw to be reloaded later */ yamato_device->pfp_fw = (unsigned int *) kmalloc(fw->size, GFP_KERNEL); if (yamato_device->pfp_fw == NULL) { KGSL_DRV_ERR("ERROR: couldn't kmalloc fw size= %d.\n", fw->size); status = -EINVAL; goto error_release_fw; } memcpy(yamato_device->pfp_fw, fw->data, fw->size); } else { fw_ptr = yamato_device->pfp_fw; fw_word_size = yamato_device->pfp_fw_size; } KGSL_DRV_INFO("loading pfp ucode version: %d\n", fw_ptr[0]); kgsl_yamato_regwrite(device, REG_CP_PFP_UCODE_ADDR, 0); for (i = 1; i < fw_word_size; i++) kgsl_yamato_regwrite(device, REG_CP_PFP_UCODE_DATA, fw_ptr[i]); error_release_fw: if (fw) release_firmware(fw); return status; }
void kgsl_cp_intrcallback(struct kgsl_device *device) { unsigned int status = 0, num_reads = 0, master_status = 0; struct kgsl_yamato_device *yamato_device = (struct kgsl_yamato_device *) device; struct kgsl_ringbuffer *rb = &device->ringbuffer; KGSL_CMD_VDBG("enter (device=%p)\n", device); kgsl_yamato_regread(device, REG_MASTER_INT_SIGNAL, &master_status); while (!status && (num_reads < VALID_STATUS_COUNT_MAX) && (master_status & MASTER_INT_SIGNAL__CP_INT_STAT)) { kgsl_yamato_regread(device, REG_CP_INT_STATUS, &status); kgsl_yamato_regread(device, REG_MASTER_INT_SIGNAL, &master_status); num_reads++; } if (num_reads > 1) KGSL_DRV_WARN("Looped %d times to read REG_CP_INT_STATUS\n", num_reads); if (!status) { if (master_status & MASTER_INT_SIGNAL__CP_INT_STAT) { KGSL_DRV_WARN("Unable to read CP_INT_STATUS\n"); wake_up_interruptible_all(&yamato_device->ib1_wq); } else KGSL_DRV_WARN("Spurious interrput detected\n"); return; } if (status & CP_INT_CNTL__RB_INT_MASK) { unsigned int enableflag = 0; kgsl_sharedmem_writel(&rb->device->memstore, KGSL_DEVICE_MEMSTORE_OFFSET(ts_cmp_enable), enableflag); wmb(); KGSL_CMD_WARN("ringbuffer rb interrupt\n"); } if (status & CP_INT_CNTL__T0_PACKET_IN_IB_MASK) { KGSL_CMD_FATAL("ringbuffer TO packet in IB interrupt\n"); kgsl_yamato_regwrite(rb->device, REG_CP_INT_CNTL, 0); kgsl_ringbuffer_dump(rb); } if (status & CP_INT_CNTL__OPCODE_ERROR_MASK) { KGSL_CMD_FATAL("ringbuffer opcode error interrupt\n"); kgsl_yamato_regwrite(rb->device, REG_CP_INT_CNTL, 0); kgsl_ringbuffer_dump(rb); } if (status & CP_INT_CNTL__PROTECTED_MODE_ERROR_MASK) { KGSL_CMD_FATAL("ringbuffer protected mode error interrupt\n"); kgsl_yamato_regwrite(rb->device, REG_CP_INT_CNTL, 0); kgsl_ringbuffer_dump(rb); } if (status & CP_INT_CNTL__RESERVED_BIT_ERROR_MASK) { KGSL_CMD_FATAL("ringbuffer reserved bit error interrupt\n"); kgsl_yamato_regwrite(rb->device, REG_CP_INT_CNTL, 0); kgsl_ringbuffer_dump(rb); } if (status & CP_INT_CNTL__IB_ERROR_MASK) { KGSL_CMD_FATAL("ringbuffer IB error interrupt\n"); kgsl_yamato_regwrite(rb->device, REG_CP_INT_CNTL, 0); kgsl_ringbuffer_dump(rb); } if (status & CP_INT_CNTL__SW_INT_MASK) KGSL_CMD_DBG("ringbuffer software interrupt\n"); if (status & CP_INT_CNTL__IB2_INT_MASK) KGSL_CMD_DBG("ringbuffer ib2 interrupt\n"); if (status & (~GSL_CP_INT_MASK)) KGSL_CMD_DBG("bad bits in REG_CP_INT_STATUS %08x\n", status); status &= GSL_CP_INT_MASK; kgsl_yamato_regwrite(device, REG_CP_INT_ACK, status); if (status & (CP_INT_CNTL__IB1_INT_MASK | CP_INT_CNTL__RB_INT_MASK)) { KGSL_CMD_WARN("ringbuffer ib1/rb interrupt\n"); wake_up_interruptible_all(&yamato_device->ib1_wq); atomic_notifier_call_chain(&(device->ts_notifier_list), KGSL_DEVICE_YAMATO, NULL); } KGSL_CMD_VDBG("return\n"); }
int kgsl_mmu_init(struct kgsl_device *device) { /* * intialize device mmu * * call this with the global lock held */ int status; uint32_t flags; struct kgsl_mmu *mmu = &device->mmu; #ifdef _DEBUG struct kgsl_mmu_debug regs; #endif /* _DEBUG */ KGSL_MEM_VDBG("enter (device=%p)\n", device); if (mmu->flags & KGSL_FLAGS_INITIALIZED0) { KGSL_MEM_INFO("MMU already initialized.\n"); return 0; } mmu->device = device; #ifndef CONFIG_MSM_KGSL_MMU mmu->config = 0x00000000; #endif /* setup MMU and sub-client behavior */ kgsl_yamato_regwrite(device, REG_MH_MMU_CONFIG, mmu->config); /* enable axi interrupts */ KGSL_MEM_DBG("enabling mmu interrupts mask=0x%08lx\n", GSL_MMU_INT_MASK); kgsl_yamato_regwrite(device, REG_MH_INTERRUPT_MASK, GSL_MMU_INT_MASK); mmu->flags |= KGSL_FLAGS_INITIALIZED0; /* MMU not enabled */ if ((mmu->config & 0x1) == 0) { KGSL_MEM_VDBG("return %d\n", 0); return 0; } /* idle device */ kgsl_yamato_idle(device, KGSL_TIMEOUT_DEFAULT); /* make sure aligned to pagesize */ BUG_ON(mmu->mpu_base & (KGSL_PAGESIZE - 1)); BUG_ON((mmu->mpu_base + mmu->mpu_range) & (KGSL_PAGESIZE - 1)); /* define physical memory range accessible by the core */ kgsl_yamato_regwrite(device, REG_MH_MMU_MPU_BASE, mmu->mpu_base); kgsl_yamato_regwrite(device, REG_MH_MMU_MPU_END, mmu->mpu_base + mmu->mpu_range); /* enable axi interrupts */ KGSL_MEM_DBG("enabling mmu interrupts mask=0x%08lx\n", GSL_MMU_INT_MASK | MH_INTERRUPT_MASK__MMU_PAGE_FAULT); kgsl_yamato_regwrite(device, REG_MH_INTERRUPT_MASK, GSL_MMU_INT_MASK | MH_INTERRUPT_MASK__MMU_PAGE_FAULT); mmu->flags |= KGSL_FLAGS_INITIALIZED; /* sub-client MMU lookups require address translation */ if ((mmu->config & ~0x1) > 0) { /*make sure virtual address range is a multiple of 64Kb */ BUG_ON(mmu->va_range & ((1 << 16) - 1)); /* allocate memory used for completing r/w operations that * cannot be mapped by the MMU */ flags = (KGSL_MEMFLAGS_ALIGN4K | KGSL_MEMFLAGS_CONPHYS | KGSL_MEMFLAGS_STRICTREQUEST); status = kgsl_sharedmem_alloc(flags, 64, &mmu->dummyspace); if (status != 0) { KGSL_MEM_ERR ("Unable to allocate dummy space memory.\n"); kgsl_mmu_close(device); return status; } kgsl_sharedmem_set(&mmu->dummyspace, 0, 0, mmu->dummyspace.size); /* TRAN_ERROR needs a 32 byte (32 byte aligned) chunk of memory * to complete transactions in case of an MMU fault. Note that * we'll leave the bottom 32 bytes of the dummyspace for other * purposes (e.g. use it when dummy read cycles are needed * for other blocks */ kgsl_yamato_regwrite(device, REG_MH_MMU_TRAN_ERROR, mmu->dummyspace.physaddr + 32); mmu->defaultpagetable = kgsl_mmu_createpagetableobject(mmu); if (!mmu->defaultpagetable) { KGSL_MEM_ERR("Failed to create global page table\n"); kgsl_mmu_close(device); return -ENOMEM; } mmu->hwpagetable = mmu->defaultpagetable; kgsl_yamato_regwrite(device, REG_MH_MMU_PT_BASE, mmu->hwpagetable->base.gpuaddr); kgsl_yamato_regwrite(device, REG_MH_MMU_VA_RANGE, (mmu->hwpagetable->va_base | (mmu->hwpagetable->va_range >> 16))); status = kgsl_yamato_setstate(device, KGSL_MMUFLAGS_TLBFLUSH); if (status) { kgsl_mmu_close(device); return status; } mmu->flags |= KGSL_FLAGS_STARTED; }