162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * caam descriptor construction helper functions 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 2008-2012 Freescale Semiconductor, Inc. 662306a36Sopenharmony_ci * Copyright 2019 NXP 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#ifndef DESC_CONSTR_H 1062306a36Sopenharmony_ci#define DESC_CONSTR_H 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include "desc.h" 1362306a36Sopenharmony_ci#include "regs.h" 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#define IMMEDIATE (1 << 23) 1662306a36Sopenharmony_ci#define CAAM_CMD_SZ sizeof(u32) 1762306a36Sopenharmony_ci#define CAAM_PTR_SZ caam_ptr_sz 1862306a36Sopenharmony_ci#define CAAM_PTR_SZ_MAX sizeof(dma_addr_t) 1962306a36Sopenharmony_ci#define CAAM_PTR_SZ_MIN sizeof(u32) 2062306a36Sopenharmony_ci#define CAAM_DESC_BYTES_MAX (CAAM_CMD_SZ * MAX_CAAM_DESCSIZE) 2162306a36Sopenharmony_ci#define __DESC_JOB_IO_LEN(n) (CAAM_CMD_SZ * 5 + (n) * 3) 2262306a36Sopenharmony_ci#define DESC_JOB_IO_LEN __DESC_JOB_IO_LEN(CAAM_PTR_SZ) 2362306a36Sopenharmony_ci#define DESC_JOB_IO_LEN_MAX __DESC_JOB_IO_LEN(CAAM_PTR_SZ_MAX) 2462306a36Sopenharmony_ci#define DESC_JOB_IO_LEN_MIN __DESC_JOB_IO_LEN(CAAM_PTR_SZ_MIN) 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci/* 2762306a36Sopenharmony_ci * The CAAM QI hardware constructs a job descriptor which points 2862306a36Sopenharmony_ci * to shared descriptor (as pointed by context_a of FQ to CAAM). 2962306a36Sopenharmony_ci * When the job descriptor is executed by deco, the whole job 3062306a36Sopenharmony_ci * descriptor together with shared descriptor gets loaded in 3162306a36Sopenharmony_ci * deco buffer which is 64 words long (each 32-bit). 3262306a36Sopenharmony_ci * 3362306a36Sopenharmony_ci * The job descriptor constructed by QI hardware has layout: 3462306a36Sopenharmony_ci * 3562306a36Sopenharmony_ci * HEADER (1 word) 3662306a36Sopenharmony_ci * Shdesc ptr (1 or 2 words) 3762306a36Sopenharmony_ci * SEQ_OUT_PTR (1 word) 3862306a36Sopenharmony_ci * Out ptr (1 or 2 words) 3962306a36Sopenharmony_ci * Out length (1 word) 4062306a36Sopenharmony_ci * SEQ_IN_PTR (1 word) 4162306a36Sopenharmony_ci * In ptr (1 or 2 words) 4262306a36Sopenharmony_ci * In length (1 word) 4362306a36Sopenharmony_ci * 4462306a36Sopenharmony_ci * The shdesc ptr is used to fetch shared descriptor contents 4562306a36Sopenharmony_ci * into deco buffer. 4662306a36Sopenharmony_ci * 4762306a36Sopenharmony_ci * Apart from shdesc contents, the total number of words that 4862306a36Sopenharmony_ci * get loaded in deco buffer are '8' or '11'. The remaining words 4962306a36Sopenharmony_ci * in deco buffer can be used for storing shared descriptor. 5062306a36Sopenharmony_ci */ 5162306a36Sopenharmony_ci#define MAX_SDLEN ((CAAM_DESC_BYTES_MAX - DESC_JOB_IO_LEN_MIN) / CAAM_CMD_SZ) 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci#ifdef DEBUG 5462306a36Sopenharmony_ci#define PRINT_POS do { printk(KERN_DEBUG "%02d: %s\n", desc_len(desc),\ 5562306a36Sopenharmony_ci &__func__[sizeof("append")]); } while (0) 5662306a36Sopenharmony_ci#else 5762306a36Sopenharmony_ci#define PRINT_POS 5862306a36Sopenharmony_ci#endif 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci#define SET_OK_NO_PROP_ERRORS (IMMEDIATE | LDST_CLASS_DECO | \ 6162306a36Sopenharmony_ci LDST_SRCDST_WORD_DECOCTRL | \ 6262306a36Sopenharmony_ci (LDOFF_CHG_SHARE_OK_NO_PROP << \ 6362306a36Sopenharmony_ci LDST_OFFSET_SHIFT)) 6462306a36Sopenharmony_ci#define DISABLE_AUTO_INFO_FIFO (IMMEDIATE | LDST_CLASS_DECO | \ 6562306a36Sopenharmony_ci LDST_SRCDST_WORD_DECOCTRL | \ 6662306a36Sopenharmony_ci (LDOFF_DISABLE_AUTO_NFIFO << LDST_OFFSET_SHIFT)) 6762306a36Sopenharmony_ci#define ENABLE_AUTO_INFO_FIFO (IMMEDIATE | LDST_CLASS_DECO | \ 6862306a36Sopenharmony_ci LDST_SRCDST_WORD_DECOCTRL | \ 6962306a36Sopenharmony_ci (LDOFF_ENABLE_AUTO_NFIFO << LDST_OFFSET_SHIFT)) 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ciextern bool caam_little_end; 7262306a36Sopenharmony_ciextern size_t caam_ptr_sz; 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci/* 7562306a36Sopenharmony_ci * HW fetches 4 S/G table entries at a time, irrespective of how many entries 7662306a36Sopenharmony_ci * are in the table. It's SW's responsibility to make sure these accesses 7762306a36Sopenharmony_ci * do not have side effects. 7862306a36Sopenharmony_ci */ 7962306a36Sopenharmony_cistatic inline int pad_sg_nents(int sg_nents) 8062306a36Sopenharmony_ci{ 8162306a36Sopenharmony_ci return ALIGN(sg_nents, 4); 8262306a36Sopenharmony_ci} 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_cistatic inline int desc_len(u32 * const desc) 8562306a36Sopenharmony_ci{ 8662306a36Sopenharmony_ci return caam32_to_cpu(*desc) & HDR_DESCLEN_MASK; 8762306a36Sopenharmony_ci} 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_cistatic inline int desc_bytes(void * const desc) 9062306a36Sopenharmony_ci{ 9162306a36Sopenharmony_ci return desc_len(desc) * CAAM_CMD_SZ; 9262306a36Sopenharmony_ci} 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_cistatic inline u32 *desc_end(u32 * const desc) 9562306a36Sopenharmony_ci{ 9662306a36Sopenharmony_ci return desc + desc_len(desc); 9762306a36Sopenharmony_ci} 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_cistatic inline void *sh_desc_pdb(u32 * const desc) 10062306a36Sopenharmony_ci{ 10162306a36Sopenharmony_ci return desc + 1; 10262306a36Sopenharmony_ci} 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_cistatic inline void init_desc(u32 * const desc, u32 options) 10562306a36Sopenharmony_ci{ 10662306a36Sopenharmony_ci *desc = cpu_to_caam32((options | HDR_ONE) + 1); 10762306a36Sopenharmony_ci} 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_cistatic inline void init_sh_desc(u32 * const desc, u32 options) 11062306a36Sopenharmony_ci{ 11162306a36Sopenharmony_ci PRINT_POS; 11262306a36Sopenharmony_ci init_desc(desc, CMD_SHARED_DESC_HDR | options); 11362306a36Sopenharmony_ci} 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_cistatic inline void init_sh_desc_pdb(u32 * const desc, u32 options, 11662306a36Sopenharmony_ci size_t pdb_bytes) 11762306a36Sopenharmony_ci{ 11862306a36Sopenharmony_ci u32 pdb_len = (pdb_bytes + CAAM_CMD_SZ - 1) / CAAM_CMD_SZ; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci init_sh_desc(desc, (((pdb_len + 1) << HDR_START_IDX_SHIFT) + pdb_len) | 12162306a36Sopenharmony_ci options); 12262306a36Sopenharmony_ci} 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_cistatic inline void init_job_desc(u32 * const desc, u32 options) 12562306a36Sopenharmony_ci{ 12662306a36Sopenharmony_ci init_desc(desc, CMD_DESC_HDR | options); 12762306a36Sopenharmony_ci} 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_cistatic inline void init_job_desc_pdb(u32 * const desc, u32 options, 13062306a36Sopenharmony_ci size_t pdb_bytes) 13162306a36Sopenharmony_ci{ 13262306a36Sopenharmony_ci u32 pdb_len = (pdb_bytes + CAAM_CMD_SZ - 1) / CAAM_CMD_SZ; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci init_job_desc(desc, (((pdb_len + 1) << HDR_START_IDX_SHIFT)) | options); 13562306a36Sopenharmony_ci} 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_cistatic inline void append_ptr(u32 * const desc, dma_addr_t ptr) 13862306a36Sopenharmony_ci{ 13962306a36Sopenharmony_ci if (caam_ptr_sz == sizeof(dma_addr_t)) { 14062306a36Sopenharmony_ci dma_addr_t *offset = (dma_addr_t *)desc_end(desc); 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci *offset = cpu_to_caam_dma(ptr); 14362306a36Sopenharmony_ci } else { 14462306a36Sopenharmony_ci u32 *offset = (u32 *)desc_end(desc); 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci *offset = cpu_to_caam_dma(ptr); 14762306a36Sopenharmony_ci } 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci (*desc) = cpu_to_caam32(caam32_to_cpu(*desc) + 15062306a36Sopenharmony_ci CAAM_PTR_SZ / CAAM_CMD_SZ); 15162306a36Sopenharmony_ci} 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_cistatic inline void init_job_desc_shared(u32 * const desc, dma_addr_t ptr, 15462306a36Sopenharmony_ci int len, u32 options) 15562306a36Sopenharmony_ci{ 15662306a36Sopenharmony_ci PRINT_POS; 15762306a36Sopenharmony_ci init_job_desc(desc, HDR_SHARED | options | 15862306a36Sopenharmony_ci (len << HDR_START_IDX_SHIFT)); 15962306a36Sopenharmony_ci append_ptr(desc, ptr); 16062306a36Sopenharmony_ci} 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_cistatic inline void append_data(u32 * const desc, const void *data, int len) 16362306a36Sopenharmony_ci{ 16462306a36Sopenharmony_ci u32 *offset = desc_end(desc); 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci /* Avoid gcc warning: memcpy with data == NULL */ 16762306a36Sopenharmony_ci if (!IS_ENABLED(CONFIG_CRYPTO_DEV_FSL_CAAM_DEBUG) || data) 16862306a36Sopenharmony_ci memcpy(offset, data, len); 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci (*desc) = cpu_to_caam32(caam32_to_cpu(*desc) + 17162306a36Sopenharmony_ci (len + CAAM_CMD_SZ - 1) / CAAM_CMD_SZ); 17262306a36Sopenharmony_ci} 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_cistatic inline void append_cmd(u32 * const desc, u32 command) 17562306a36Sopenharmony_ci{ 17662306a36Sopenharmony_ci u32 *cmd = desc_end(desc); 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci *cmd = cpu_to_caam32(command); 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci (*desc) = cpu_to_caam32(caam32_to_cpu(*desc) + 1); 18162306a36Sopenharmony_ci} 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci#define append_u32 append_cmd 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_cistatic inline void append_u64(u32 * const desc, u64 data) 18662306a36Sopenharmony_ci{ 18762306a36Sopenharmony_ci u32 *offset = desc_end(desc); 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci /* Only 32-bit alignment is guaranteed in descriptor buffer */ 19062306a36Sopenharmony_ci if (caam_little_end) { 19162306a36Sopenharmony_ci *offset = cpu_to_caam32(lower_32_bits(data)); 19262306a36Sopenharmony_ci *(++offset) = cpu_to_caam32(upper_32_bits(data)); 19362306a36Sopenharmony_ci } else { 19462306a36Sopenharmony_ci *offset = cpu_to_caam32(upper_32_bits(data)); 19562306a36Sopenharmony_ci *(++offset) = cpu_to_caam32(lower_32_bits(data)); 19662306a36Sopenharmony_ci } 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci (*desc) = cpu_to_caam32(caam32_to_cpu(*desc) + 2); 19962306a36Sopenharmony_ci} 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci/* Write command without affecting header, and return pointer to next word */ 20262306a36Sopenharmony_cistatic inline u32 *write_cmd(u32 * const desc, u32 command) 20362306a36Sopenharmony_ci{ 20462306a36Sopenharmony_ci *desc = cpu_to_caam32(command); 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci return desc + 1; 20762306a36Sopenharmony_ci} 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_cistatic inline void append_cmd_ptr(u32 * const desc, dma_addr_t ptr, int len, 21062306a36Sopenharmony_ci u32 command) 21162306a36Sopenharmony_ci{ 21262306a36Sopenharmony_ci append_cmd(desc, command | len); 21362306a36Sopenharmony_ci append_ptr(desc, ptr); 21462306a36Sopenharmony_ci} 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci/* Write length after pointer, rather than inside command */ 21762306a36Sopenharmony_cistatic inline void append_cmd_ptr_extlen(u32 * const desc, dma_addr_t ptr, 21862306a36Sopenharmony_ci unsigned int len, u32 command) 21962306a36Sopenharmony_ci{ 22062306a36Sopenharmony_ci append_cmd(desc, command); 22162306a36Sopenharmony_ci if (!(command & (SQIN_RTO | SQIN_PRE))) 22262306a36Sopenharmony_ci append_ptr(desc, ptr); 22362306a36Sopenharmony_ci append_cmd(desc, len); 22462306a36Sopenharmony_ci} 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_cistatic inline void append_cmd_data(u32 * const desc, const void *data, int len, 22762306a36Sopenharmony_ci u32 command) 22862306a36Sopenharmony_ci{ 22962306a36Sopenharmony_ci append_cmd(desc, command | IMMEDIATE | len); 23062306a36Sopenharmony_ci append_data(desc, data, len); 23162306a36Sopenharmony_ci} 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci#define APPEND_CMD_RET(cmd, op) \ 23462306a36Sopenharmony_cistatic inline u32 *append_##cmd(u32 * const desc, u32 options) \ 23562306a36Sopenharmony_ci{ \ 23662306a36Sopenharmony_ci u32 *cmd = desc_end(desc); \ 23762306a36Sopenharmony_ci PRINT_POS; \ 23862306a36Sopenharmony_ci append_cmd(desc, CMD_##op | options); \ 23962306a36Sopenharmony_ci return cmd; \ 24062306a36Sopenharmony_ci} 24162306a36Sopenharmony_ciAPPEND_CMD_RET(jump, JUMP) 24262306a36Sopenharmony_ciAPPEND_CMD_RET(move, MOVE) 24362306a36Sopenharmony_ciAPPEND_CMD_RET(move_len, MOVE_LEN) 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_cistatic inline void set_jump_tgt_here(u32 * const desc, u32 *jump_cmd) 24662306a36Sopenharmony_ci{ 24762306a36Sopenharmony_ci *jump_cmd = cpu_to_caam32(caam32_to_cpu(*jump_cmd) | 24862306a36Sopenharmony_ci (desc_len(desc) - (jump_cmd - desc))); 24962306a36Sopenharmony_ci} 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_cistatic inline void set_move_tgt_here(u32 * const desc, u32 *move_cmd) 25262306a36Sopenharmony_ci{ 25362306a36Sopenharmony_ci u32 val = caam32_to_cpu(*move_cmd); 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci val &= ~MOVE_OFFSET_MASK; 25662306a36Sopenharmony_ci val |= (desc_len(desc) << (MOVE_OFFSET_SHIFT + 2)) & MOVE_OFFSET_MASK; 25762306a36Sopenharmony_ci *move_cmd = cpu_to_caam32(val); 25862306a36Sopenharmony_ci} 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci#define APPEND_CMD(cmd, op) \ 26162306a36Sopenharmony_cistatic inline void append_##cmd(u32 * const desc, u32 options) \ 26262306a36Sopenharmony_ci{ \ 26362306a36Sopenharmony_ci PRINT_POS; \ 26462306a36Sopenharmony_ci append_cmd(desc, CMD_##op | options); \ 26562306a36Sopenharmony_ci} 26662306a36Sopenharmony_ciAPPEND_CMD(operation, OPERATION) 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci#define APPEND_CMD_LEN(cmd, op) \ 26962306a36Sopenharmony_cistatic inline void append_##cmd(u32 * const desc, unsigned int len, \ 27062306a36Sopenharmony_ci u32 options) \ 27162306a36Sopenharmony_ci{ \ 27262306a36Sopenharmony_ci PRINT_POS; \ 27362306a36Sopenharmony_ci append_cmd(desc, CMD_##op | len | options); \ 27462306a36Sopenharmony_ci} 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ciAPPEND_CMD_LEN(seq_load, SEQ_LOAD) 27762306a36Sopenharmony_ciAPPEND_CMD_LEN(seq_store, SEQ_STORE) 27862306a36Sopenharmony_ciAPPEND_CMD_LEN(seq_fifo_load, SEQ_FIFO_LOAD) 27962306a36Sopenharmony_ciAPPEND_CMD_LEN(seq_fifo_store, SEQ_FIFO_STORE) 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci#define APPEND_CMD_PTR(cmd, op) \ 28262306a36Sopenharmony_cistatic inline void append_##cmd(u32 * const desc, dma_addr_t ptr, \ 28362306a36Sopenharmony_ci unsigned int len, u32 options) \ 28462306a36Sopenharmony_ci{ \ 28562306a36Sopenharmony_ci PRINT_POS; \ 28662306a36Sopenharmony_ci append_cmd_ptr(desc, ptr, len, CMD_##op | options); \ 28762306a36Sopenharmony_ci} 28862306a36Sopenharmony_ciAPPEND_CMD_PTR(key, KEY) 28962306a36Sopenharmony_ciAPPEND_CMD_PTR(load, LOAD) 29062306a36Sopenharmony_ciAPPEND_CMD_PTR(fifo_load, FIFO_LOAD) 29162306a36Sopenharmony_ciAPPEND_CMD_PTR(fifo_store, FIFO_STORE) 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_cistatic inline void append_store(u32 * const desc, dma_addr_t ptr, 29462306a36Sopenharmony_ci unsigned int len, u32 options) 29562306a36Sopenharmony_ci{ 29662306a36Sopenharmony_ci u32 cmd_src; 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci cmd_src = options & LDST_SRCDST_MASK; 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci append_cmd(desc, CMD_STORE | options | len); 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci /* The following options do not require pointer */ 30362306a36Sopenharmony_ci if (!(cmd_src == LDST_SRCDST_WORD_DESCBUF_SHARED || 30462306a36Sopenharmony_ci cmd_src == LDST_SRCDST_WORD_DESCBUF_JOB || 30562306a36Sopenharmony_ci cmd_src == LDST_SRCDST_WORD_DESCBUF_JOB_WE || 30662306a36Sopenharmony_ci cmd_src == LDST_SRCDST_WORD_DESCBUF_SHARED_WE)) 30762306a36Sopenharmony_ci append_ptr(desc, ptr); 30862306a36Sopenharmony_ci} 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci#define APPEND_SEQ_PTR_INTLEN(cmd, op) \ 31162306a36Sopenharmony_cistatic inline void append_seq_##cmd##_ptr_intlen(u32 * const desc, \ 31262306a36Sopenharmony_ci dma_addr_t ptr, \ 31362306a36Sopenharmony_ci unsigned int len, \ 31462306a36Sopenharmony_ci u32 options) \ 31562306a36Sopenharmony_ci{ \ 31662306a36Sopenharmony_ci PRINT_POS; \ 31762306a36Sopenharmony_ci if (options & (SQIN_RTO | SQIN_PRE)) \ 31862306a36Sopenharmony_ci append_cmd(desc, CMD_SEQ_##op##_PTR | len | options); \ 31962306a36Sopenharmony_ci else \ 32062306a36Sopenharmony_ci append_cmd_ptr(desc, ptr, len, CMD_SEQ_##op##_PTR | options); \ 32162306a36Sopenharmony_ci} 32262306a36Sopenharmony_ciAPPEND_SEQ_PTR_INTLEN(in, IN) 32362306a36Sopenharmony_ciAPPEND_SEQ_PTR_INTLEN(out, OUT) 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci#define APPEND_CMD_PTR_TO_IMM(cmd, op) \ 32662306a36Sopenharmony_cistatic inline void append_##cmd##_as_imm(u32 * const desc, const void *data, \ 32762306a36Sopenharmony_ci unsigned int len, u32 options) \ 32862306a36Sopenharmony_ci{ \ 32962306a36Sopenharmony_ci PRINT_POS; \ 33062306a36Sopenharmony_ci append_cmd_data(desc, data, len, CMD_##op | options); \ 33162306a36Sopenharmony_ci} 33262306a36Sopenharmony_ciAPPEND_CMD_PTR_TO_IMM(load, LOAD); 33362306a36Sopenharmony_ciAPPEND_CMD_PTR_TO_IMM(fifo_load, FIFO_LOAD); 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci#define APPEND_CMD_PTR_EXTLEN(cmd, op) \ 33662306a36Sopenharmony_cistatic inline void append_##cmd##_extlen(u32 * const desc, dma_addr_t ptr, \ 33762306a36Sopenharmony_ci unsigned int len, u32 options) \ 33862306a36Sopenharmony_ci{ \ 33962306a36Sopenharmony_ci PRINT_POS; \ 34062306a36Sopenharmony_ci append_cmd_ptr_extlen(desc, ptr, len, CMD_##op | SQIN_EXT | options); \ 34162306a36Sopenharmony_ci} 34262306a36Sopenharmony_ciAPPEND_CMD_PTR_EXTLEN(seq_in_ptr, SEQ_IN_PTR) 34362306a36Sopenharmony_ciAPPEND_CMD_PTR_EXTLEN(seq_out_ptr, SEQ_OUT_PTR) 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci/* 34662306a36Sopenharmony_ci * Determine whether to store length internally or externally depending on 34762306a36Sopenharmony_ci * the size of its type 34862306a36Sopenharmony_ci */ 34962306a36Sopenharmony_ci#define APPEND_CMD_PTR_LEN(cmd, op, type) \ 35062306a36Sopenharmony_cistatic inline void append_##cmd(u32 * const desc, dma_addr_t ptr, \ 35162306a36Sopenharmony_ci type len, u32 options) \ 35262306a36Sopenharmony_ci{ \ 35362306a36Sopenharmony_ci PRINT_POS; \ 35462306a36Sopenharmony_ci if (sizeof(type) > sizeof(u16)) \ 35562306a36Sopenharmony_ci append_##cmd##_extlen(desc, ptr, len, options); \ 35662306a36Sopenharmony_ci else \ 35762306a36Sopenharmony_ci append_##cmd##_intlen(desc, ptr, len, options); \ 35862306a36Sopenharmony_ci} 35962306a36Sopenharmony_ciAPPEND_CMD_PTR_LEN(seq_in_ptr, SEQ_IN_PTR, u32) 36062306a36Sopenharmony_ciAPPEND_CMD_PTR_LEN(seq_out_ptr, SEQ_OUT_PTR, u32) 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci/* 36362306a36Sopenharmony_ci * 2nd variant for commands whose specified immediate length differs 36462306a36Sopenharmony_ci * from length of immediate data provided, e.g., split keys 36562306a36Sopenharmony_ci */ 36662306a36Sopenharmony_ci#define APPEND_CMD_PTR_TO_IMM2(cmd, op) \ 36762306a36Sopenharmony_cistatic inline void append_##cmd##_as_imm(u32 * const desc, const void *data, \ 36862306a36Sopenharmony_ci unsigned int data_len, \ 36962306a36Sopenharmony_ci unsigned int len, u32 options) \ 37062306a36Sopenharmony_ci{ \ 37162306a36Sopenharmony_ci PRINT_POS; \ 37262306a36Sopenharmony_ci append_cmd(desc, CMD_##op | IMMEDIATE | len | options); \ 37362306a36Sopenharmony_ci append_data(desc, data, data_len); \ 37462306a36Sopenharmony_ci} 37562306a36Sopenharmony_ciAPPEND_CMD_PTR_TO_IMM2(key, KEY); 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci#define APPEND_CMD_RAW_IMM(cmd, op, type) \ 37862306a36Sopenharmony_cistatic inline void append_##cmd##_imm_##type(u32 * const desc, type immediate, \ 37962306a36Sopenharmony_ci u32 options) \ 38062306a36Sopenharmony_ci{ \ 38162306a36Sopenharmony_ci PRINT_POS; \ 38262306a36Sopenharmony_ci if (options & LDST_LEN_MASK) \ 38362306a36Sopenharmony_ci append_cmd(desc, CMD_##op | IMMEDIATE | options); \ 38462306a36Sopenharmony_ci else \ 38562306a36Sopenharmony_ci append_cmd(desc, CMD_##op | IMMEDIATE | options | \ 38662306a36Sopenharmony_ci sizeof(type)); \ 38762306a36Sopenharmony_ci append_cmd(desc, immediate); \ 38862306a36Sopenharmony_ci} 38962306a36Sopenharmony_ciAPPEND_CMD_RAW_IMM(load, LOAD, u32); 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci/* 39262306a36Sopenharmony_ci * ee - endianness 39362306a36Sopenharmony_ci * size - size of immediate type in bytes 39462306a36Sopenharmony_ci */ 39562306a36Sopenharmony_ci#define APPEND_CMD_RAW_IMM2(cmd, op, ee, size) \ 39662306a36Sopenharmony_cistatic inline void append_##cmd##_imm_##ee##size(u32 *desc, \ 39762306a36Sopenharmony_ci u##size immediate, \ 39862306a36Sopenharmony_ci u32 options) \ 39962306a36Sopenharmony_ci{ \ 40062306a36Sopenharmony_ci __##ee##size data = cpu_to_##ee##size(immediate); \ 40162306a36Sopenharmony_ci PRINT_POS; \ 40262306a36Sopenharmony_ci append_cmd(desc, CMD_##op | IMMEDIATE | options | sizeof(data)); \ 40362306a36Sopenharmony_ci append_data(desc, &data, sizeof(data)); \ 40462306a36Sopenharmony_ci} 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ciAPPEND_CMD_RAW_IMM2(load, LOAD, be, 32); 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci/* 40962306a36Sopenharmony_ci * Append math command. Only the last part of destination and source need to 41062306a36Sopenharmony_ci * be specified 41162306a36Sopenharmony_ci */ 41262306a36Sopenharmony_ci#define APPEND_MATH(op, desc, dest, src_0, src_1, len) \ 41362306a36Sopenharmony_ciappend_cmd(desc, CMD_MATH | MATH_FUN_##op | MATH_DEST_##dest | \ 41462306a36Sopenharmony_ci MATH_SRC0_##src_0 | MATH_SRC1_##src_1 | (u32)len); 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci#define append_math_add(desc, dest, src0, src1, len) \ 41762306a36Sopenharmony_ci APPEND_MATH(ADD, desc, dest, src0, src1, len) 41862306a36Sopenharmony_ci#define append_math_sub(desc, dest, src0, src1, len) \ 41962306a36Sopenharmony_ci APPEND_MATH(SUB, desc, dest, src0, src1, len) 42062306a36Sopenharmony_ci#define append_math_add_c(desc, dest, src0, src1, len) \ 42162306a36Sopenharmony_ci APPEND_MATH(ADDC, desc, dest, src0, src1, len) 42262306a36Sopenharmony_ci#define append_math_sub_b(desc, dest, src0, src1, len) \ 42362306a36Sopenharmony_ci APPEND_MATH(SUBB, desc, dest, src0, src1, len) 42462306a36Sopenharmony_ci#define append_math_and(desc, dest, src0, src1, len) \ 42562306a36Sopenharmony_ci APPEND_MATH(AND, desc, dest, src0, src1, len) 42662306a36Sopenharmony_ci#define append_math_or(desc, dest, src0, src1, len) \ 42762306a36Sopenharmony_ci APPEND_MATH(OR, desc, dest, src0, src1, len) 42862306a36Sopenharmony_ci#define append_math_xor(desc, dest, src0, src1, len) \ 42962306a36Sopenharmony_ci APPEND_MATH(XOR, desc, dest, src0, src1, len) 43062306a36Sopenharmony_ci#define append_math_lshift(desc, dest, src0, src1, len) \ 43162306a36Sopenharmony_ci APPEND_MATH(LSHIFT, desc, dest, src0, src1, len) 43262306a36Sopenharmony_ci#define append_math_rshift(desc, dest, src0, src1, len) \ 43362306a36Sopenharmony_ci APPEND_MATH(RSHIFT, desc, dest, src0, src1, len) 43462306a36Sopenharmony_ci#define append_math_ldshift(desc, dest, src0, src1, len) \ 43562306a36Sopenharmony_ci APPEND_MATH(SHLD, desc, dest, src0, src1, len) 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci/* Exactly one source is IMM. Data is passed in as u32 value */ 43862306a36Sopenharmony_ci#define APPEND_MATH_IMM_u32(op, desc, dest, src_0, src_1, data) \ 43962306a36Sopenharmony_cido { \ 44062306a36Sopenharmony_ci APPEND_MATH(op, desc, dest, src_0, src_1, CAAM_CMD_SZ); \ 44162306a36Sopenharmony_ci append_cmd(desc, data); \ 44262306a36Sopenharmony_ci} while (0) 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci#define append_math_add_imm_u32(desc, dest, src0, src1, data) \ 44562306a36Sopenharmony_ci APPEND_MATH_IMM_u32(ADD, desc, dest, src0, src1, data) 44662306a36Sopenharmony_ci#define append_math_sub_imm_u32(desc, dest, src0, src1, data) \ 44762306a36Sopenharmony_ci APPEND_MATH_IMM_u32(SUB, desc, dest, src0, src1, data) 44862306a36Sopenharmony_ci#define append_math_add_c_imm_u32(desc, dest, src0, src1, data) \ 44962306a36Sopenharmony_ci APPEND_MATH_IMM_u32(ADDC, desc, dest, src0, src1, data) 45062306a36Sopenharmony_ci#define append_math_sub_b_imm_u32(desc, dest, src0, src1, data) \ 45162306a36Sopenharmony_ci APPEND_MATH_IMM_u32(SUBB, desc, dest, src0, src1, data) 45262306a36Sopenharmony_ci#define append_math_and_imm_u32(desc, dest, src0, src1, data) \ 45362306a36Sopenharmony_ci APPEND_MATH_IMM_u32(AND, desc, dest, src0, src1, data) 45462306a36Sopenharmony_ci#define append_math_or_imm_u32(desc, dest, src0, src1, data) \ 45562306a36Sopenharmony_ci APPEND_MATH_IMM_u32(OR, desc, dest, src0, src1, data) 45662306a36Sopenharmony_ci#define append_math_xor_imm_u32(desc, dest, src0, src1, data) \ 45762306a36Sopenharmony_ci APPEND_MATH_IMM_u32(XOR, desc, dest, src0, src1, data) 45862306a36Sopenharmony_ci#define append_math_lshift_imm_u32(desc, dest, src0, src1, data) \ 45962306a36Sopenharmony_ci APPEND_MATH_IMM_u32(LSHIFT, desc, dest, src0, src1, data) 46062306a36Sopenharmony_ci#define append_math_rshift_imm_u32(desc, dest, src0, src1, data) \ 46162306a36Sopenharmony_ci APPEND_MATH_IMM_u32(RSHIFT, desc, dest, src0, src1, data) 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci/* Exactly one source is IMM. Data is passed in as u64 value */ 46462306a36Sopenharmony_ci#define APPEND_MATH_IMM_u64(op, desc, dest, src_0, src_1, data) \ 46562306a36Sopenharmony_cido { \ 46662306a36Sopenharmony_ci u32 upper = (data >> 16) >> 16; \ 46762306a36Sopenharmony_ci APPEND_MATH(op, desc, dest, src_0, src_1, CAAM_CMD_SZ * 2 | \ 46862306a36Sopenharmony_ci (upper ? 0 : MATH_IFB)); \ 46962306a36Sopenharmony_ci if (upper) \ 47062306a36Sopenharmony_ci append_u64(desc, data); \ 47162306a36Sopenharmony_ci else \ 47262306a36Sopenharmony_ci append_u32(desc, lower_32_bits(data)); \ 47362306a36Sopenharmony_ci} while (0) 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci#define append_math_add_imm_u64(desc, dest, src0, src1, data) \ 47662306a36Sopenharmony_ci APPEND_MATH_IMM_u64(ADD, desc, dest, src0, src1, data) 47762306a36Sopenharmony_ci#define append_math_sub_imm_u64(desc, dest, src0, src1, data) \ 47862306a36Sopenharmony_ci APPEND_MATH_IMM_u64(SUB, desc, dest, src0, src1, data) 47962306a36Sopenharmony_ci#define append_math_add_c_imm_u64(desc, dest, src0, src1, data) \ 48062306a36Sopenharmony_ci APPEND_MATH_IMM_u64(ADDC, desc, dest, src0, src1, data) 48162306a36Sopenharmony_ci#define append_math_sub_b_imm_u64(desc, dest, src0, src1, data) \ 48262306a36Sopenharmony_ci APPEND_MATH_IMM_u64(SUBB, desc, dest, src0, src1, data) 48362306a36Sopenharmony_ci#define append_math_and_imm_u64(desc, dest, src0, src1, data) \ 48462306a36Sopenharmony_ci APPEND_MATH_IMM_u64(AND, desc, dest, src0, src1, data) 48562306a36Sopenharmony_ci#define append_math_or_imm_u64(desc, dest, src0, src1, data) \ 48662306a36Sopenharmony_ci APPEND_MATH_IMM_u64(OR, desc, dest, src0, src1, data) 48762306a36Sopenharmony_ci#define append_math_xor_imm_u64(desc, dest, src0, src1, data) \ 48862306a36Sopenharmony_ci APPEND_MATH_IMM_u64(XOR, desc, dest, src0, src1, data) 48962306a36Sopenharmony_ci#define append_math_lshift_imm_u64(desc, dest, src0, src1, data) \ 49062306a36Sopenharmony_ci APPEND_MATH_IMM_u64(LSHIFT, desc, dest, src0, src1, data) 49162306a36Sopenharmony_ci#define append_math_rshift_imm_u64(desc, dest, src0, src1, data) \ 49262306a36Sopenharmony_ci APPEND_MATH_IMM_u64(RSHIFT, desc, dest, src0, src1, data) 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci/** 49562306a36Sopenharmony_ci * struct alginfo - Container for algorithm details 49662306a36Sopenharmony_ci * @algtype: algorithm selector; for valid values, see documentation of the 49762306a36Sopenharmony_ci * functions where it is used. 49862306a36Sopenharmony_ci * @keylen: length of the provided algorithm key, in bytes 49962306a36Sopenharmony_ci * @keylen_pad: padded length of the provided algorithm key, in bytes 50062306a36Sopenharmony_ci * @key_dma: dma (bus) address where algorithm key resides 50162306a36Sopenharmony_ci * @key_virt: virtual address where algorithm key resides 50262306a36Sopenharmony_ci * @key_inline: true - key can be inlined in the descriptor; false - key is 50362306a36Sopenharmony_ci * referenced by the descriptor 50462306a36Sopenharmony_ci */ 50562306a36Sopenharmony_cistruct alginfo { 50662306a36Sopenharmony_ci u32 algtype; 50762306a36Sopenharmony_ci unsigned int keylen; 50862306a36Sopenharmony_ci unsigned int keylen_pad; 50962306a36Sopenharmony_ci dma_addr_t key_dma; 51062306a36Sopenharmony_ci const void *key_virt; 51162306a36Sopenharmony_ci bool key_inline; 51262306a36Sopenharmony_ci}; 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci/** 51562306a36Sopenharmony_ci * desc_inline_query() - Provide indications on which data items can be inlined 51662306a36Sopenharmony_ci * and which shall be referenced in a shared descriptor. 51762306a36Sopenharmony_ci * @sd_base_len: Shared descriptor base length - bytes consumed by the commands, 51862306a36Sopenharmony_ci * excluding the data items to be inlined (or corresponding 51962306a36Sopenharmony_ci * pointer if an item is not inlined). Each cnstr_* function that 52062306a36Sopenharmony_ci * generates descriptors should have a define mentioning 52162306a36Sopenharmony_ci * corresponding length. 52262306a36Sopenharmony_ci * @jd_len: Maximum length of the job descriptor(s) that will be used 52362306a36Sopenharmony_ci * together with the shared descriptor. 52462306a36Sopenharmony_ci * @data_len: Array of lengths of the data items trying to be inlined 52562306a36Sopenharmony_ci * @inl_mask: 32bit mask with bit x = 1 if data item x can be inlined, 0 52662306a36Sopenharmony_ci * otherwise. 52762306a36Sopenharmony_ci * @count: Number of data items (size of @data_len array); must be <= 32 52862306a36Sopenharmony_ci * 52962306a36Sopenharmony_ci * Return: 0 if data can be inlined / referenced, negative value if not. If 0, 53062306a36Sopenharmony_ci * check @inl_mask for details. 53162306a36Sopenharmony_ci */ 53262306a36Sopenharmony_cistatic inline int desc_inline_query(unsigned int sd_base_len, 53362306a36Sopenharmony_ci unsigned int jd_len, unsigned int *data_len, 53462306a36Sopenharmony_ci u32 *inl_mask, unsigned int count) 53562306a36Sopenharmony_ci{ 53662306a36Sopenharmony_ci int rem_bytes = (int)(CAAM_DESC_BYTES_MAX - sd_base_len - jd_len); 53762306a36Sopenharmony_ci unsigned int i; 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci *inl_mask = 0; 54062306a36Sopenharmony_ci for (i = 0; (i < count) && (rem_bytes > 0); i++) { 54162306a36Sopenharmony_ci if (rem_bytes - (int)(data_len[i] + 54262306a36Sopenharmony_ci (count - i - 1) * CAAM_PTR_SZ) >= 0) { 54362306a36Sopenharmony_ci rem_bytes -= data_len[i]; 54462306a36Sopenharmony_ci *inl_mask |= (1 << i); 54562306a36Sopenharmony_ci } else { 54662306a36Sopenharmony_ci rem_bytes -= CAAM_PTR_SZ; 54762306a36Sopenharmony_ci } 54862306a36Sopenharmony_ci } 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci return (rem_bytes >= 0) ? 0 : -1; 55162306a36Sopenharmony_ci} 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci/** 55462306a36Sopenharmony_ci * append_proto_dkp - Derived Key Protocol (DKP): key -> split key 55562306a36Sopenharmony_ci * @desc: pointer to buffer used for descriptor construction 55662306a36Sopenharmony_ci * @adata: pointer to authentication transform definitions. 55762306a36Sopenharmony_ci * keylen should be the length of initial key, while keylen_pad 55862306a36Sopenharmony_ci * the length of the derived (split) key. 55962306a36Sopenharmony_ci * Valid algorithm values - one of OP_ALG_ALGSEL_{MD5, SHA1, SHA224, 56062306a36Sopenharmony_ci * SHA256, SHA384, SHA512}. 56162306a36Sopenharmony_ci */ 56262306a36Sopenharmony_cistatic inline void append_proto_dkp(u32 * const desc, struct alginfo *adata) 56362306a36Sopenharmony_ci{ 56462306a36Sopenharmony_ci u32 protid; 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci /* 56762306a36Sopenharmony_ci * Quick & dirty translation from OP_ALG_ALGSEL_{MD5, SHA*} 56862306a36Sopenharmony_ci * to OP_PCLID_DKP_{MD5, SHA*} 56962306a36Sopenharmony_ci */ 57062306a36Sopenharmony_ci protid = (adata->algtype & OP_ALG_ALGSEL_SUBMASK) | 57162306a36Sopenharmony_ci (0x20 << OP_ALG_ALGSEL_SHIFT); 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci if (adata->key_inline) { 57462306a36Sopenharmony_ci int words; 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci if (adata->keylen > adata->keylen_pad) { 57762306a36Sopenharmony_ci append_operation(desc, OP_TYPE_UNI_PROTOCOL | protid | 57862306a36Sopenharmony_ci OP_PCL_DKP_SRC_PTR | 57962306a36Sopenharmony_ci OP_PCL_DKP_DST_IMM | adata->keylen); 58062306a36Sopenharmony_ci append_ptr(desc, adata->key_dma); 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci words = (ALIGN(adata->keylen_pad, CAAM_CMD_SZ) - 58362306a36Sopenharmony_ci CAAM_PTR_SZ) / CAAM_CMD_SZ; 58462306a36Sopenharmony_ci } else { 58562306a36Sopenharmony_ci append_operation(desc, OP_TYPE_UNI_PROTOCOL | protid | 58662306a36Sopenharmony_ci OP_PCL_DKP_SRC_IMM | 58762306a36Sopenharmony_ci OP_PCL_DKP_DST_IMM | adata->keylen); 58862306a36Sopenharmony_ci append_data(desc, adata->key_virt, adata->keylen); 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci words = (ALIGN(adata->keylen_pad, CAAM_CMD_SZ) - 59162306a36Sopenharmony_ci ALIGN(adata->keylen, CAAM_CMD_SZ)) / 59262306a36Sopenharmony_ci CAAM_CMD_SZ; 59362306a36Sopenharmony_ci } 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_ci /* Reserve space in descriptor buffer for the derived key */ 59662306a36Sopenharmony_ci if (words) 59762306a36Sopenharmony_ci (*desc) = cpu_to_caam32(caam32_to_cpu(*desc) + words); 59862306a36Sopenharmony_ci } else { 59962306a36Sopenharmony_ci append_operation(desc, OP_TYPE_UNI_PROTOCOL | protid | 60062306a36Sopenharmony_ci OP_PCL_DKP_SRC_PTR | OP_PCL_DKP_DST_PTR | 60162306a36Sopenharmony_ci adata->keylen); 60262306a36Sopenharmony_ci append_ptr(desc, adata->key_dma); 60362306a36Sopenharmony_ci } 60462306a36Sopenharmony_ci} 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci#endif /* DESC_CONSTR_H */ 607