static int ccp5_do_cmd(struct ccp5_desc *desc, struct ccp_cmd_queue *cmd_q) { u32 *mP; __le32 *dP; u32 tail; int i; int ret = 0; cmd_q->total_ops++; if (CCP5_CMD_SOC(desc)) { CCP5_CMD_IOC(desc) = 1; CCP5_CMD_SOC(desc) = 0; } mutex_lock(&cmd_q->q_mutex); mP = (u32 *) &cmd_q->qbase[cmd_q->qidx]; dP = (__le32 *) desc; for (i = 0; i < 8; i++) mP[i] = cpu_to_le32(dP[i]); /* handle endianness */ cmd_q->qidx = (cmd_q->qidx + 1) % COMMANDS_PER_QUEUE; /* The data used by this command must be flushed to memory */ wmb(); /* Write the new tail address back to the queue register */ tail = low_address(cmd_q->qdma_tail + cmd_q->qidx * Q_DESC_SIZE); iowrite32(tail, cmd_q->reg_tail_lo); /* Turn the queue back on using our cached control register */ iowrite32(cmd_q->qcontrol | CMD5_Q_RUN, cmd_q->reg_control); mutex_unlock(&cmd_q->q_mutex); if (CCP5_CMD_IOC(desc)) { /* Wait for the job to complete */ ret = wait_event_interruptible(cmd_q->int_queue, cmd_q->int_rcvd); if (ret || cmd_q->cmd_error) { /* Log the error and flush the queue by * moving the head pointer */ if (cmd_q->cmd_error) ccp_log_error(cmd_q->ccp, cmd_q->cmd_error); iowrite32(tail, cmd_q->reg_head_lo); if (!ret) ret = -EIO; } cmd_q->int_rcvd = 0; } return ret; }
static int ccp5_perform_ecc(struct ccp_op *op) { struct ccp5_desc desc; union ccp_function function; /* Zero out all the fields of the command desc */ memset(&desc, 0, Q_DESC_SIZE); CCP5_CMD_ENGINE(&desc) = CCP_ENGINE_ECC; CCP5_CMD_SOC(&desc) = 0; CCP5_CMD_IOC(&desc) = 1; CCP5_CMD_INIT(&desc) = 0; CCP5_CMD_EOM(&desc) = 1; CCP5_CMD_PROT(&desc) = 0; function.raw = 0; function.ecc.mode = op->u.ecc.function; CCP5_CMD_FUNCTION(&desc) = function.raw; CCP5_CMD_LEN(&desc) = op->src.u.dma.length; CCP5_CMD_SRC_LO(&desc) = ccp_addr_lo(&op->src.u.dma); CCP5_CMD_SRC_HI(&desc) = ccp_addr_hi(&op->src.u.dma); CCP5_CMD_SRC_MEM(&desc) = CCP_MEMTYPE_SYSTEM; CCP5_CMD_DST_LO(&desc) = ccp_addr_lo(&op->dst.u.dma); CCP5_CMD_DST_HI(&desc) = ccp_addr_hi(&op->dst.u.dma); CCP5_CMD_DST_MEM(&desc) = CCP_MEMTYPE_SYSTEM; return ccp5_do_cmd(&desc, op->cmd_q); }
static int ccp5_perform_passthru(struct ccp_op *op) { struct ccp5_desc desc; union ccp_function function; struct ccp_dma_info *saddr = &op->src.u.dma; struct ccp_dma_info *daddr = &op->dst.u.dma; op->cmd_q->total_pt_ops++; memset(&desc, 0, Q_DESC_SIZE); CCP5_CMD_ENGINE(&desc) = CCP_ENGINE_PASSTHRU; CCP5_CMD_SOC(&desc) = 0; CCP5_CMD_IOC(&desc) = 1; CCP5_CMD_INIT(&desc) = 0; CCP5_CMD_EOM(&desc) = op->eom; CCP5_CMD_PROT(&desc) = 0; function.raw = 0; CCP_PT_BYTESWAP(&function) = op->u.passthru.byte_swap; CCP_PT_BITWISE(&function) = op->u.passthru.bit_mod; CCP5_CMD_FUNCTION(&desc) = function.raw; /* Length of source data is always 256 bytes */ if (op->src.type == CCP_MEMTYPE_SYSTEM) CCP5_CMD_LEN(&desc) = saddr->length; else CCP5_CMD_LEN(&desc) = daddr->length; if (op->src.type == CCP_MEMTYPE_SYSTEM) { CCP5_CMD_SRC_LO(&desc) = ccp_addr_lo(&op->src.u.dma); CCP5_CMD_SRC_HI(&desc) = ccp_addr_hi(&op->src.u.dma); CCP5_CMD_SRC_MEM(&desc) = CCP_MEMTYPE_SYSTEM; if (op->u.passthru.bit_mod != CCP_PASSTHRU_BITWISE_NOOP) CCP5_CMD_LSB_ID(&desc) = op->sb_key; } else { u32 key_addr = op->src.u.sb * CCP_SB_BYTES; CCP5_CMD_SRC_LO(&desc) = lower_32_bits(key_addr); CCP5_CMD_SRC_HI(&desc) = 0; CCP5_CMD_SRC_MEM(&desc) = CCP_MEMTYPE_SB; } if (op->dst.type == CCP_MEMTYPE_SYSTEM) { CCP5_CMD_DST_LO(&desc) = ccp_addr_lo(&op->dst.u.dma); CCP5_CMD_DST_HI(&desc) = ccp_addr_hi(&op->dst.u.dma); CCP5_CMD_DST_MEM(&desc) = CCP_MEMTYPE_SYSTEM; } else { u32 key_addr = op->dst.u.sb * CCP_SB_BYTES; CCP5_CMD_DST_LO(&desc) = lower_32_bits(key_addr); CCP5_CMD_DST_HI(&desc) = 0; CCP5_CMD_DST_MEM(&desc) = CCP_MEMTYPE_SB; } return ccp5_do_cmd(&desc, op->cmd_q); }
static int ccp5_perform_aes(struct ccp_op *op) { struct ccp5_desc desc; union ccp_function function; u32 key_addr = op->sb_key * LSB_ITEM_SIZE; op->cmd_q->total_aes_ops++; /* Zero out all the fields of the command desc */ memset(&desc, 0, Q_DESC_SIZE); CCP5_CMD_ENGINE(&desc) = CCP_ENGINE_AES; CCP5_CMD_SOC(&desc) = op->soc; CCP5_CMD_IOC(&desc) = 1; CCP5_CMD_INIT(&desc) = op->init; CCP5_CMD_EOM(&desc) = op->eom; CCP5_CMD_PROT(&desc) = 0; function.raw = 0; CCP_AES_ENCRYPT(&function) = op->u.aes.action; CCP_AES_MODE(&function) = op->u.aes.mode; CCP_AES_TYPE(&function) = op->u.aes.type; CCP_AES_SIZE(&function) = op->u.aes.size; CCP5_CMD_FUNCTION(&desc) = function.raw; CCP5_CMD_LEN(&desc) = op->src.u.dma.length; CCP5_CMD_SRC_LO(&desc) = ccp_addr_lo(&op->src.u.dma); CCP5_CMD_SRC_HI(&desc) = ccp_addr_hi(&op->src.u.dma); CCP5_CMD_SRC_MEM(&desc) = CCP_MEMTYPE_SYSTEM; CCP5_CMD_DST_LO(&desc) = ccp_addr_lo(&op->dst.u.dma); CCP5_CMD_DST_HI(&desc) = ccp_addr_hi(&op->dst.u.dma); CCP5_CMD_DST_MEM(&desc) = CCP_MEMTYPE_SYSTEM; CCP5_CMD_KEY_LO(&desc) = lower_32_bits(key_addr); CCP5_CMD_KEY_HI(&desc) = 0; CCP5_CMD_KEY_MEM(&desc) = CCP_MEMTYPE_SB; CCP5_CMD_LSB_ID(&desc) = op->sb_ctx; return ccp5_do_cmd(&desc, op->cmd_q); }
static int ccp5_perform_rsa(struct ccp_op *op) { struct ccp5_desc desc; union ccp_function function; op->cmd_q->total_rsa_ops++; /* Zero out all the fields of the command desc */ memset(&desc, 0, Q_DESC_SIZE); CCP5_CMD_ENGINE(&desc) = CCP_ENGINE_RSA; CCP5_CMD_SOC(&desc) = op->soc; CCP5_CMD_IOC(&desc) = 1; CCP5_CMD_INIT(&desc) = 0; CCP5_CMD_EOM(&desc) = 1; CCP5_CMD_PROT(&desc) = 0; function.raw = 0; CCP_RSA_SIZE(&function) = (op->u.rsa.mod_size + 7) >> 3; CCP5_CMD_FUNCTION(&desc) = function.raw; CCP5_CMD_LEN(&desc) = op->u.rsa.input_len; /* Source is from external memory */ CCP5_CMD_SRC_LO(&desc) = ccp_addr_lo(&op->src.u.dma); CCP5_CMD_SRC_HI(&desc) = ccp_addr_hi(&op->src.u.dma); CCP5_CMD_SRC_MEM(&desc) = CCP_MEMTYPE_SYSTEM; /* Destination is in external memory */ CCP5_CMD_DST_LO(&desc) = ccp_addr_lo(&op->dst.u.dma); CCP5_CMD_DST_HI(&desc) = ccp_addr_hi(&op->dst.u.dma); CCP5_CMD_DST_MEM(&desc) = CCP_MEMTYPE_SYSTEM; /* Key (Exponent) is in external memory */ CCP5_CMD_KEY_LO(&desc) = ccp_addr_lo(&op->exp.u.dma); CCP5_CMD_KEY_HI(&desc) = ccp_addr_hi(&op->exp.u.dma); CCP5_CMD_KEY_MEM(&desc) = CCP_MEMTYPE_SYSTEM; return ccp5_do_cmd(&desc, op->cmd_q); }
static int ccp5_perform_sha(struct ccp_op *op) { struct ccp5_desc desc; union ccp_function function; op->cmd_q->total_sha_ops++; /* Zero out all the fields of the command desc */ memset(&desc, 0, Q_DESC_SIZE); CCP5_CMD_ENGINE(&desc) = CCP_ENGINE_SHA; CCP5_CMD_SOC(&desc) = op->soc; CCP5_CMD_IOC(&desc) = 1; CCP5_CMD_INIT(&desc) = 1; CCP5_CMD_EOM(&desc) = op->eom; CCP5_CMD_PROT(&desc) = 0; function.raw = 0; CCP_SHA_TYPE(&function) = op->u.sha.type; CCP5_CMD_FUNCTION(&desc) = function.raw; CCP5_CMD_LEN(&desc) = op->src.u.dma.length; CCP5_CMD_SRC_LO(&desc) = ccp_addr_lo(&op->src.u.dma); CCP5_CMD_SRC_HI(&desc) = ccp_addr_hi(&op->src.u.dma); CCP5_CMD_SRC_MEM(&desc) = CCP_MEMTYPE_SYSTEM; CCP5_CMD_LSB_ID(&desc) = op->sb_ctx; if (op->eom) { CCP5_CMD_SHA_LO(&desc) = lower_32_bits(op->u.sha.msg_bits); CCP5_CMD_SHA_HI(&desc) = upper_32_bits(op->u.sha.msg_bits); } else { CCP5_CMD_SHA_LO(&desc) = 0; CCP5_CMD_SHA_HI(&desc) = 0; } return ccp5_do_cmd(&desc, op->cmd_q); }