int32_t cmdqRecWriteFromDataRegister(cmdqRecHandle handle, CMDQ_DATA_REGISTER_ENUM srcDataReg, uint32_t hwRegAddr) { #ifdef CMDQ_GPR_SUPPORT const uint32_t subsys = cmdq_subsys_from_phys_addr(hwRegAddr); const uint32_t subsysBit = cmdq_core_get_subsys_LSB_in_argA(); /* write HW register(argA) with data of GPR data register(argB)*/ return cmdq_append_command(handle, CMDQ_CODE_WRITE, hwRegAddr, srcDataReg, 0, 1); #else CMDQ_ERR("func:%s failed since CMDQ dosen't support GPR\n", __func__); return -EFAULT; #endif /* CMDQ_GPR_SUPPORT */ }
/** * centralize the write/polling/read command for APB and GPR handle * this function must be called inside cmdq_append_command * because we ignore buffer and pre-fetch check here. * Parameter: * same as cmdq_append_command * Return: * same as cmdq_append_command */ static int32_t cmdq_append_wpr_command(cmdqRecHandle handle, CMDQ_CODE_ENUM code, uint32_t argA, uint32_t argB, uint32_t argAType, uint32_t argBType) { int32_t subsys; uint32_t *pCommand; bool bUseGPR = false; /* use new argA to present final inserted argA*/ uint32_t newArgA; uint32_t newArgAType = argAType; uint32_t argType = 0; /* be careful that subsys encoding position is different among platforms */ const uint32_t subsysBit = cmdq_core_get_subsys_LSB_in_argA(); pCommand = (uint32_t *) ((uint8_t *) handle->pBuffer + handle->blockSize); if (CMDQ_CODE_READ != code && CMDQ_CODE_WRITE != code && CMDQ_CODE_POLL != code){ CMDQ_ERR("Record 0x%p, flow error, should not append comment in wpr API", handle); return -EFAULT; } /* we must re-calculate current PC at first. */ pCommand = (uint32_t *) ((uint8_t *) handle->pBuffer + handle->blockSize); CMDQ_VERBOSE("REC: 0x%p CMD: 0x%p, op: 0x%02x\n", handle, pCommand, code); CMDQ_VERBOSE("REC: 0x%p CMD: argA: 0x%08x, argB: 0x%08x, argAType: %d, argBType: %d\n", handle, argA, argB, argAType, argBType); if (0 == argAType){ /* argA is the HW register address to read from */ subsys = cmdq_subsys_from_phys_addr(argA); if (CMDQ_SPECIAL_SUBSYS_ADDR == subsys){ #ifdef CMDQ_GPR_SUPPORT bUseGPR = true; CMDQ_MSG("REC: Special handle memory base address 0x%08x\n", argA); /* Wait and clear for GPR mutex token to enter mutex*/ *pCommand++ = ((1 << 31) | (1 << 15) | 1); *pCommand++ = (CMDQ_CODE_WFE << 24) | CMDQ_SYNC_TOKEN_GPR_SET_4; handle->blockSize += CMDQ_INST_SIZE; /* Move extra handle APB address to GPR*/ *pCommand++ = argA; *pCommand++ = (CMDQ_CODE_MOVE << 24) | ((CMDQ_DATA_REG_DEBUG & 0x1f) << 16) | (4 << 21); handle->blockSize += CMDQ_INST_SIZE; /* change final argA to GPR */ newArgA = ((CMDQ_DATA_REG_DEBUG & 0x1f) << 16); if (argA & 0x1){ /* MASK case, set final bit to 1*/ newArgA = newArgA | 0x1; } /* change argA type to 1*/ newArgAType = 1; #else CMDQ_ERR("func:%s failed since CMDQ dosen't support GPR\n", __func__); return -EFAULT; #endif }else if (0 == argAType && 0 > subsys){ CMDQ_ERR("REC: Unsupported memory base address 0x%08x\n", argA); return -EFAULT; }else{ /* compose final argA according to subsys table */ newArgA = (argA & 0xffff) | ((subsys & 0x1f) << subsysBit); } }else{ /* compose final argA according GPR value */ newArgA = ((argA & 0x1f) << 16); } argType = (newArgAType << 2) | (argBType << 1); /* newArgA is the HW register address to access from or GPR value store the HW register address */ /* argB is the value or register id */ /* bit 55: argA type, 1 for GPR */ /* bit 54: argB type, 1 for GPR */ /* argType: ('newArgAType', 'argBType', '0') */ *pCommand++ = argB; *pCommand++ = (code << 24) | newArgA | (argType << 21); handle->blockSize += CMDQ_INST_SIZE; if (bUseGPR) { /* Set for GPR mutex token to leave mutex*/ *pCommand++ = ((1 << 31) | (1 << 16)); *pCommand++ = (CMDQ_CODE_WFE << 24) | CMDQ_SYNC_TOKEN_GPR_SET_4; handle->blockSize += CMDQ_INST_SIZE; } return 0; }
int32_t cmdq_append_command(cmdqRecHandle handle, CMDQ_CODE_ENUM code, uint32_t argA, uint32_t argB) { int32_t subsys; uint32_t *pCommand; /* be careful that subsys encoding position is different among platforms */ const uint32_t subsysBit = cmdq_core_get_subsys_LSB_in_argA(); pCommand = (uint32_t *) ((uint8_t *) handle->pBuffer + handle->blockSize); if (handle->finalized) { CMDQ_ERR("Already finalized record 0x%p, cannot add more command", handle); return -EBUSY; } /* check if we have sufficient buffer size */ /* we leave a 4 instruction (4 bytes each) margin. */ if ((handle->blockSize + 32) >= handle->bufferSize) { if (0 != cmdq_rec_realloc_cmd_buffer(handle, handle->bufferSize * 2)) { return -ENOMEM; } } /* force insert MARKER if prefetch memory is full */ /* GCE deadlocks if we don't do so */ if (CMDQ_CODE_EOC != code && cmdq_core_should_enable_prefetch(handle->scenario)) { if (handle->prefetchCount >= CMDQ_MAX_PREFETCH_INSTUCTION) { /* Mark END of prefetch section */ cmdqRecMark(handle); /* BEGING of next prefetch section */ cmdqRecMark(handle); } else { ++handle->prefetchCount; } } /* we must re-calculate current PC because we may already insert MARKER inst. */ pCommand = (uint32_t *) ((uint8_t *) handle->pBuffer + handle->blockSize); CMDQ_VERBOSE("REC: 0x%p CMD: 0x%p, op: 0x%02x, argA: 0x%08x, argB: 0x%08x\n", handle, pCommand, code, argA, argB); switch (code) { case CMDQ_CODE_READ: /* argA is the HW register address to read from */ subsys = cmdq_subsys_from_phys_addr(argA); /* argB is the register id to read into */ /* bit 54: argB type, 1 for GPR */ *pCommand++ = argB; *pCommand++ = (CMDQ_CODE_READ << 24) | (argA & 0xffff) | ((subsys & 0x1f) << subsysBit) | (2 << 21); break; case CMDQ_CODE_MOVE: *pCommand++ = argB; *pCommand++ = CMDQ_CODE_MOVE << 24 | (argA & 0xffffff); break; case CMDQ_CODE_WRITE: subsys = cmdq_subsys_from_phys_addr(argA); if (-1 == subsys) { CMDQ_ERR("REC: Unsupported memory base address 0x%08x\n", argA); return -EFAULT; } *pCommand++ = argB; *pCommand++ = (CMDQ_CODE_WRITE << 24) | (argA & 0x0FFFF) | ((subsys & 0x01F) << subsysBit); break; case CMDQ_CODE_POLL: subsys = cmdq_subsys_from_phys_addr(argA); if (-1 == subsys) { CMDQ_ERR("REC: Unsupported memory base address 0x%08x\n", argA); return -EFAULT; } *pCommand++ = argB; *pCommand++ = (CMDQ_CODE_POLL << 24) | (argA & 0x0FFFF) | ((subsys & 0x01F) << subsysBit); break; case CMDQ_CODE_JUMP: *pCommand++ = argB; *pCommand++ = (CMDQ_CODE_JUMP << 24) | (argA & 0x0FFFFFF); break; case CMDQ_CODE_WFE: /* bit 0-11: wait_value, 1 */ /* bit 15: to_wait, true */ /* bit 31: to_update, true */ /* bit 16-27: update_value, 0 */ *pCommand++ = ((1 << 31) | (1 << 15) | 1); *pCommand++ = (CMDQ_CODE_WFE << 24) | argA; break; case CMDQ_CODE_SET_TOKEN: /* this is actually WFE(SYNC) but with different parameter */ /* interpretation */ /* bit 15: to_wait, false */ /* bit 31: to_update, true */ /* bit 16-27: update_value, 1 */ *pCommand++ = ((1 << 31) | (1 << 16)); *pCommand++ = (CMDQ_CODE_WFE << 24) | argA; break; case CMDQ_CODE_WAIT_NO_CLEAR: /* bit 0-11: wait_value, 1 */ /* bit 15: to_wait, true */ /* bit 31: to_update, false */ *pCommand++ = ((0 << 31) | (1 << 15) | 1); *pCommand++ = (CMDQ_CODE_WFE << 24) | argA; break; case CMDQ_CODE_CLEAR_TOKEN: /* this is actually WFE(SYNC) but with different parameter */ /* interpretation */ /* bit 15: to_wait, false */ /* bit 31: to_update, true */ /* bit 16-27: update_value, 0 */ *pCommand++ = ((1 << 31) | (0 << 16)); *pCommand++ = (CMDQ_CODE_WFE << 24) | argA; break; case CMDQ_CODE_EOC: *pCommand++ = argB; *pCommand++ = (CMDQ_CODE_EOC << 24) | (argA & 0x0FFFFFF); break; case CMDQ_CODE_RAW: *pCommand++ = argB; *pCommand++ = argA; break; default: return -EFAULT; } handle->blockSize += 8; return 0; }