1 /* SPDX-License-Identifier: GPL-2.0 */
3 * caam descriptor construction helper functions
5 * Copyright 2008-2012 Freescale Semiconductor, Inc.
14 #define IMMEDIATE (1 << 23)
15 #define CAAM_CMD_SZ sizeof(u32)
16 #define CAAM_PTR_SZ sizeof(dma_addr_t)
17 #define CAAM_DESC_BYTES_MAX (CAAM_CMD_SZ * MAX_CAAM_DESCSIZE)
18 #define DESC_JOB_IO_LEN (CAAM_CMD_SZ * 5 + CAAM_PTR_SZ * 3)
21 #define PRINT_POS do { printk(KERN_DEBUG "%02d: %s\n", desc_len(desc),\
22 &__func__[sizeof("append")]); } while (0)
27 #define SET_OK_NO_PROP_ERRORS (IMMEDIATE | LDST_CLASS_DECO | \
28 LDST_SRCDST_WORD_DECOCTRL | \
29 (LDOFF_CHG_SHARE_OK_NO_PROP << \
31 #define DISABLE_AUTO_INFO_FIFO (IMMEDIATE | LDST_CLASS_DECO | \
32 LDST_SRCDST_WORD_DECOCTRL | \
33 (LDOFF_DISABLE_AUTO_NFIFO << LDST_OFFSET_SHIFT))
34 #define ENABLE_AUTO_INFO_FIFO (IMMEDIATE | LDST_CLASS_DECO | \
35 LDST_SRCDST_WORD_DECOCTRL | \
36 (LDOFF_ENABLE_AUTO_NFIFO << LDST_OFFSET_SHIFT))
38 extern bool caam_little_end
;
40 static inline int desc_len(u32
* const desc
)
42 return caam32_to_cpu(*desc
) & HDR_DESCLEN_MASK
;
45 static inline int desc_bytes(void * const desc
)
47 return desc_len(desc
) * CAAM_CMD_SZ
;
50 static inline u32
*desc_end(u32
* const desc
)
52 return desc
+ desc_len(desc
);
55 static inline void *sh_desc_pdb(u32
* const desc
)
60 static inline void init_desc(u32
* const desc
, u32 options
)
62 *desc
= cpu_to_caam32((options
| HDR_ONE
) + 1);
65 static inline void init_sh_desc(u32
* const desc
, u32 options
)
68 init_desc(desc
, CMD_SHARED_DESC_HDR
| options
);
71 static inline void init_sh_desc_pdb(u32
* const desc
, u32 options
,
74 u32 pdb_len
= (pdb_bytes
+ CAAM_CMD_SZ
- 1) / CAAM_CMD_SZ
;
76 init_sh_desc(desc
, (((pdb_len
+ 1) << HDR_START_IDX_SHIFT
) + pdb_len
) |
80 static inline void init_job_desc(u32
* const desc
, u32 options
)
82 init_desc(desc
, CMD_DESC_HDR
| options
);
85 static inline void init_job_desc_pdb(u32
* const desc
, u32 options
,
88 u32 pdb_len
= (pdb_bytes
+ CAAM_CMD_SZ
- 1) / CAAM_CMD_SZ
;
90 init_job_desc(desc
, (((pdb_len
+ 1) << HDR_START_IDX_SHIFT
)) | options
);
93 static inline void append_ptr(u32
* const desc
, dma_addr_t ptr
)
95 dma_addr_t
*offset
= (dma_addr_t
*)desc_end(desc
);
97 *offset
= cpu_to_caam_dma(ptr
);
99 (*desc
) = cpu_to_caam32(caam32_to_cpu(*desc
) +
100 CAAM_PTR_SZ
/ CAAM_CMD_SZ
);
103 static inline void init_job_desc_shared(u32
* const desc
, dma_addr_t ptr
,
104 int len
, u32 options
)
107 init_job_desc(desc
, HDR_SHARED
| options
|
108 (len
<< HDR_START_IDX_SHIFT
));
109 append_ptr(desc
, ptr
);
112 static inline void append_data(u32
* const desc
, const void *data
, int len
)
114 u32
*offset
= desc_end(desc
);
116 if (len
) /* avoid sparse warning: memcpy with byte count of 0 */
117 memcpy(offset
, data
, len
);
119 (*desc
) = cpu_to_caam32(caam32_to_cpu(*desc
) +
120 (len
+ CAAM_CMD_SZ
- 1) / CAAM_CMD_SZ
);
123 static inline void append_cmd(u32
* const desc
, u32 command
)
125 u32
*cmd
= desc_end(desc
);
127 *cmd
= cpu_to_caam32(command
);
129 (*desc
) = cpu_to_caam32(caam32_to_cpu(*desc
) + 1);
132 #define append_u32 append_cmd
134 static inline void append_u64(u32
* const desc
, u64 data
)
136 u32
*offset
= desc_end(desc
);
138 /* Only 32-bit alignment is guaranteed in descriptor buffer */
139 if (caam_little_end
) {
140 *offset
= cpu_to_caam32(lower_32_bits(data
));
141 *(++offset
) = cpu_to_caam32(upper_32_bits(data
));
143 *offset
= cpu_to_caam32(upper_32_bits(data
));
144 *(++offset
) = cpu_to_caam32(lower_32_bits(data
));
147 (*desc
) = cpu_to_caam32(caam32_to_cpu(*desc
) + 2);
150 /* Write command without affecting header, and return pointer to next word */
151 static inline u32
*write_cmd(u32
* const desc
, u32 command
)
153 *desc
= cpu_to_caam32(command
);
158 static inline void append_cmd_ptr(u32
* const desc
, dma_addr_t ptr
, int len
,
161 append_cmd(desc
, command
| len
);
162 append_ptr(desc
, ptr
);
165 /* Write length after pointer, rather than inside command */
166 static inline void append_cmd_ptr_extlen(u32
* const desc
, dma_addr_t ptr
,
167 unsigned int len
, u32 command
)
169 append_cmd(desc
, command
);
170 if (!(command
& (SQIN_RTO
| SQIN_PRE
)))
171 append_ptr(desc
, ptr
);
172 append_cmd(desc
, len
);
175 static inline void append_cmd_data(u32
* const desc
, const void *data
, int len
,
178 append_cmd(desc
, command
| IMMEDIATE
| len
);
179 append_data(desc
, data
, len
);
182 #define APPEND_CMD_RET(cmd, op) \
183 static inline u32 *append_##cmd(u32 * const desc, u32 options) \
185 u32 *cmd = desc_end(desc); \
187 append_cmd(desc, CMD_##op | options); \
190 APPEND_CMD_RET(jump
, JUMP
)
191 APPEND_CMD_RET(move
, MOVE
)
193 static inline void set_jump_tgt_here(u32
* const desc
, u32
*jump_cmd
)
195 *jump_cmd
= cpu_to_caam32(caam32_to_cpu(*jump_cmd
) |
196 (desc_len(desc
) - (jump_cmd
- desc
)));
199 static inline void set_move_tgt_here(u32
* const desc
, u32
*move_cmd
)
201 u32 val
= caam32_to_cpu(*move_cmd
);
203 val
&= ~MOVE_OFFSET_MASK
;
204 val
|= (desc_len(desc
) << (MOVE_OFFSET_SHIFT
+ 2)) & MOVE_OFFSET_MASK
;
205 *move_cmd
= cpu_to_caam32(val
);
208 #define APPEND_CMD(cmd, op) \
209 static inline void append_##cmd(u32 * const desc, u32 options) \
212 append_cmd(desc, CMD_##op | options); \
214 APPEND_CMD(operation
, OPERATION
)
216 #define APPEND_CMD_LEN(cmd, op) \
217 static inline void append_##cmd(u32 * const desc, unsigned int len, \
221 append_cmd(desc, CMD_##op | len | options); \
224 APPEND_CMD_LEN(seq_load
, SEQ_LOAD
)
225 APPEND_CMD_LEN(seq_store
, SEQ_STORE
)
226 APPEND_CMD_LEN(seq_fifo_load
, SEQ_FIFO_LOAD
)
227 APPEND_CMD_LEN(seq_fifo_store
, SEQ_FIFO_STORE
)
229 #define APPEND_CMD_PTR(cmd, op) \
230 static inline void append_##cmd(u32 * const desc, dma_addr_t ptr, \
231 unsigned int len, u32 options) \
234 append_cmd_ptr(desc, ptr, len, CMD_##op | options); \
236 APPEND_CMD_PTR(key
, KEY
)
237 APPEND_CMD_PTR(load
, LOAD
)
238 APPEND_CMD_PTR(fifo_load
, FIFO_LOAD
)
239 APPEND_CMD_PTR(fifo_store
, FIFO_STORE
)
241 static inline void append_store(u32
* const desc
, dma_addr_t ptr
,
242 unsigned int len
, u32 options
)
246 cmd_src
= options
& LDST_SRCDST_MASK
;
248 append_cmd(desc
, CMD_STORE
| options
| len
);
250 /* The following options do not require pointer */
251 if (!(cmd_src
== LDST_SRCDST_WORD_DESCBUF_SHARED
||
252 cmd_src
== LDST_SRCDST_WORD_DESCBUF_JOB
||
253 cmd_src
== LDST_SRCDST_WORD_DESCBUF_JOB_WE
||
254 cmd_src
== LDST_SRCDST_WORD_DESCBUF_SHARED_WE
))
255 append_ptr(desc
, ptr
);
258 #define APPEND_SEQ_PTR_INTLEN(cmd, op) \
259 static inline void append_seq_##cmd##_ptr_intlen(u32 * const desc, \
265 if (options & (SQIN_RTO | SQIN_PRE)) \
266 append_cmd(desc, CMD_SEQ_##op##_PTR | len | options); \
268 append_cmd_ptr(desc, ptr, len, CMD_SEQ_##op##_PTR | options); \
270 APPEND_SEQ_PTR_INTLEN(in
, IN
)
271 APPEND_SEQ_PTR_INTLEN(out
, OUT
)
273 #define APPEND_CMD_PTR_TO_IMM(cmd, op) \
274 static inline void append_##cmd##_as_imm(u32 * const desc, const void *data, \
275 unsigned int len, u32 options) \
278 append_cmd_data(desc, data, len, CMD_##op | options); \
280 APPEND_CMD_PTR_TO_IMM(load
, LOAD
);
281 APPEND_CMD_PTR_TO_IMM(fifo_load
, FIFO_LOAD
);
283 #define APPEND_CMD_PTR_EXTLEN(cmd, op) \
284 static inline void append_##cmd##_extlen(u32 * const desc, dma_addr_t ptr, \
285 unsigned int len, u32 options) \
288 append_cmd_ptr_extlen(desc, ptr, len, CMD_##op | SQIN_EXT | options); \
290 APPEND_CMD_PTR_EXTLEN(seq_in_ptr
, SEQ_IN_PTR
)
291 APPEND_CMD_PTR_EXTLEN(seq_out_ptr
, SEQ_OUT_PTR
)
294 * Determine whether to store length internally or externally depending on
295 * the size of its type
297 #define APPEND_CMD_PTR_LEN(cmd, op, type) \
298 static inline void append_##cmd(u32 * const desc, dma_addr_t ptr, \
299 type len, u32 options) \
302 if (sizeof(type) > sizeof(u16)) \
303 append_##cmd##_extlen(desc, ptr, len, options); \
305 append_##cmd##_intlen(desc, ptr, len, options); \
307 APPEND_CMD_PTR_LEN(seq_in_ptr
, SEQ_IN_PTR
, u32
)
308 APPEND_CMD_PTR_LEN(seq_out_ptr
, SEQ_OUT_PTR
, u32
)
311 * 2nd variant for commands whose specified immediate length differs
312 * from length of immediate data provided, e.g., split keys
314 #define APPEND_CMD_PTR_TO_IMM2(cmd, op) \
315 static inline void append_##cmd##_as_imm(u32 * const desc, const void *data, \
316 unsigned int data_len, \
317 unsigned int len, u32 options) \
320 append_cmd(desc, CMD_##op | IMMEDIATE | len | options); \
321 append_data(desc, data, data_len); \
323 APPEND_CMD_PTR_TO_IMM2(key
, KEY
);
325 #define APPEND_CMD_RAW_IMM(cmd, op, type) \
326 static inline void append_##cmd##_imm_##type(u32 * const desc, type immediate, \
330 append_cmd(desc, CMD_##op | IMMEDIATE | options | sizeof(type)); \
331 append_cmd(desc, immediate); \
333 APPEND_CMD_RAW_IMM(load
, LOAD
, u32
);
337 * size - size of immediate type in bytes
339 #define APPEND_CMD_RAW_IMM2(cmd, op, ee, size) \
340 static inline void append_##cmd##_imm_##ee##size(u32 *desc, \
344 __##ee##size data = cpu_to_##ee##size(immediate); \
346 append_cmd(desc, CMD_##op | IMMEDIATE | options | sizeof(data)); \
347 append_data(desc, &data, sizeof(data)); \
350 APPEND_CMD_RAW_IMM2(load
, LOAD
, be
, 32);
353 * Append math command. Only the last part of destination and source need to
356 #define APPEND_MATH(op, desc, dest, src_0, src_1, len) \
357 append_cmd(desc, CMD_MATH | MATH_FUN_##op | MATH_DEST_##dest | \
358 MATH_SRC0_##src_0 | MATH_SRC1_##src_1 | (u32)len);
360 #define append_math_add(desc, dest, src0, src1, len) \
361 APPEND_MATH(ADD, desc, dest, src0, src1, len)
362 #define append_math_sub(desc, dest, src0, src1, len) \
363 APPEND_MATH(SUB, desc, dest, src0, src1, len)
364 #define append_math_add_c(desc, dest, src0, src1, len) \
365 APPEND_MATH(ADDC, desc, dest, src0, src1, len)
366 #define append_math_sub_b(desc, dest, src0, src1, len) \
367 APPEND_MATH(SUBB, desc, dest, src0, src1, len)
368 #define append_math_and(desc, dest, src0, src1, len) \
369 APPEND_MATH(AND, desc, dest, src0, src1, len)
370 #define append_math_or(desc, dest, src0, src1, len) \
371 APPEND_MATH(OR, desc, dest, src0, src1, len)
372 #define append_math_xor(desc, dest, src0, src1, len) \
373 APPEND_MATH(XOR, desc, dest, src0, src1, len)
374 #define append_math_lshift(desc, dest, src0, src1, len) \
375 APPEND_MATH(LSHIFT, desc, dest, src0, src1, len)
376 #define append_math_rshift(desc, dest, src0, src1, len) \
377 APPEND_MATH(RSHIFT, desc, dest, src0, src1, len)
378 #define append_math_ldshift(desc, dest, src0, src1, len) \
379 APPEND_MATH(SHLD, desc, dest, src0, src1, len)
381 /* Exactly one source is IMM. Data is passed in as u32 value */
382 #define APPEND_MATH_IMM_u32(op, desc, dest, src_0, src_1, data) \
384 APPEND_MATH(op, desc, dest, src_0, src_1, CAAM_CMD_SZ); \
385 append_cmd(desc, data); \
388 #define append_math_add_imm_u32(desc, dest, src0, src1, data) \
389 APPEND_MATH_IMM_u32(ADD, desc, dest, src0, src1, data)
390 #define append_math_sub_imm_u32(desc, dest, src0, src1, data) \
391 APPEND_MATH_IMM_u32(SUB, desc, dest, src0, src1, data)
392 #define append_math_add_c_imm_u32(desc, dest, src0, src1, data) \
393 APPEND_MATH_IMM_u32(ADDC, desc, dest, src0, src1, data)
394 #define append_math_sub_b_imm_u32(desc, dest, src0, src1, data) \
395 APPEND_MATH_IMM_u32(SUBB, desc, dest, src0, src1, data)
396 #define append_math_and_imm_u32(desc, dest, src0, src1, data) \
397 APPEND_MATH_IMM_u32(AND, desc, dest, src0, src1, data)
398 #define append_math_or_imm_u32(desc, dest, src0, src1, data) \
399 APPEND_MATH_IMM_u32(OR, desc, dest, src0, src1, data)
400 #define append_math_xor_imm_u32(desc, dest, src0, src1, data) \
401 APPEND_MATH_IMM_u32(XOR, desc, dest, src0, src1, data)
402 #define append_math_lshift_imm_u32(desc, dest, src0, src1, data) \
403 APPEND_MATH_IMM_u32(LSHIFT, desc, dest, src0, src1, data)
404 #define append_math_rshift_imm_u32(desc, dest, src0, src1, data) \
405 APPEND_MATH_IMM_u32(RSHIFT, desc, dest, src0, src1, data)
407 /* Exactly one source is IMM. Data is passed in as u64 value */
408 #define APPEND_MATH_IMM_u64(op, desc, dest, src_0, src_1, data) \
410 u32 upper = (data >> 16) >> 16; \
411 APPEND_MATH(op, desc, dest, src_0, src_1, CAAM_CMD_SZ * 2 | \
412 (upper ? 0 : MATH_IFB)); \
414 append_u64(desc, data); \
416 append_u32(desc, lower_32_bits(data)); \
419 #define append_math_add_imm_u64(desc, dest, src0, src1, data) \
420 APPEND_MATH_IMM_u64(ADD, desc, dest, src0, src1, data)
421 #define append_math_sub_imm_u64(desc, dest, src0, src1, data) \
422 APPEND_MATH_IMM_u64(SUB, desc, dest, src0, src1, data)
423 #define append_math_add_c_imm_u64(desc, dest, src0, src1, data) \
424 APPEND_MATH_IMM_u64(ADDC, desc, dest, src0, src1, data)
425 #define append_math_sub_b_imm_u64(desc, dest, src0, src1, data) \
426 APPEND_MATH_IMM_u64(SUBB, desc, dest, src0, src1, data)
427 #define append_math_and_imm_u64(desc, dest, src0, src1, data) \
428 APPEND_MATH_IMM_u64(AND, desc, dest, src0, src1, data)
429 #define append_math_or_imm_u64(desc, dest, src0, src1, data) \
430 APPEND_MATH_IMM_u64(OR, desc, dest, src0, src1, data)
431 #define append_math_xor_imm_u64(desc, dest, src0, src1, data) \
432 APPEND_MATH_IMM_u64(XOR, desc, dest, src0, src1, data)
433 #define append_math_lshift_imm_u64(desc, dest, src0, src1, data) \
434 APPEND_MATH_IMM_u64(LSHIFT, desc, dest, src0, src1, data)
435 #define append_math_rshift_imm_u64(desc, dest, src0, src1, data) \
436 APPEND_MATH_IMM_u64(RSHIFT, desc, dest, src0, src1, data)
439 * struct alginfo - Container for algorithm details
440 * @algtype: algorithm selector; for valid values, see documentation of the
441 * functions where it is used.
442 * @keylen: length of the provided algorithm key, in bytes
443 * @keylen_pad: padded length of the provided algorithm key, in bytes
444 * @key: address where algorithm key resides; virtual address if key_inline
445 * is true, dma (bus) address if key_inline is false.
446 * @key_inline: true - key can be inlined in the descriptor; false - key is
447 * referenced by the descriptor
452 unsigned int keylen_pad
;
455 const void *key_virt
;
461 * desc_inline_query() - Provide indications on which data items can be inlined
462 * and which shall be referenced in a shared descriptor.
463 * @sd_base_len: Shared descriptor base length - bytes consumed by the commands,
464 * excluding the data items to be inlined (or corresponding
465 * pointer if an item is not inlined). Each cnstr_* function that
466 * generates descriptors should have a define mentioning
467 * corresponding length.
468 * @jd_len: Maximum length of the job descriptor(s) that will be used
469 * together with the shared descriptor.
470 * @data_len: Array of lengths of the data items trying to be inlined
471 * @inl_mask: 32bit mask with bit x = 1 if data item x can be inlined, 0
473 * @count: Number of data items (size of @data_len array); must be <= 32
475 * Return: 0 if data can be inlined / referenced, negative value if not. If 0,
476 * check @inl_mask for details.
478 static inline int desc_inline_query(unsigned int sd_base_len
,
479 unsigned int jd_len
, unsigned int *data_len
,
480 u32
*inl_mask
, unsigned int count
)
482 int rem_bytes
= (int)(CAAM_DESC_BYTES_MAX
- sd_base_len
- jd_len
);
486 for (i
= 0; (i
< count
) && (rem_bytes
> 0); i
++) {
487 if (rem_bytes
- (int)(data_len
[i
] +
488 (count
- i
- 1) * CAAM_PTR_SZ
) >= 0) {
489 rem_bytes
-= data_len
[i
];
490 *inl_mask
|= (1 << i
);
492 rem_bytes
-= CAAM_PTR_SZ
;
496 return (rem_bytes
>= 0) ? 0 : -1;
500 * append_proto_dkp - Derived Key Protocol (DKP): key -> split key
501 * @desc: pointer to buffer used for descriptor construction
502 * @adata: pointer to authentication transform definitions.
503 * keylen should be the length of initial key, while keylen_pad
504 * the length of the derived (split) key.
505 * Valid algorithm values - one of OP_ALG_ALGSEL_{MD5, SHA1, SHA224,
506 * SHA256, SHA384, SHA512}.
508 static inline void append_proto_dkp(u32
* const desc
, struct alginfo
*adata
)
513 * Quick & dirty translation from OP_ALG_ALGSEL_{MD5, SHA*}
514 * to OP_PCLID_DKP_{MD5, SHA*}
516 protid
= (adata
->algtype
& OP_ALG_ALGSEL_SUBMASK
) |
517 (0x20 << OP_ALG_ALGSEL_SHIFT
);
519 if (adata
->key_inline
) {
522 append_operation(desc
, OP_TYPE_UNI_PROTOCOL
| protid
|
523 OP_PCL_DKP_SRC_IMM
| OP_PCL_DKP_DST_IMM
|
525 append_data(desc
, adata
->key_virt
, adata
->keylen
);
527 /* Reserve space in descriptor buffer for the derived key */
528 words
= (ALIGN(adata
->keylen_pad
, CAAM_CMD_SZ
) -
529 ALIGN(adata
->keylen
, CAAM_CMD_SZ
)) / CAAM_CMD_SZ
;
531 (*desc
) = cpu_to_caam32(caam32_to_cpu(*desc
) + words
);
533 append_operation(desc
, OP_TYPE_UNI_PROTOCOL
| protid
|
534 OP_PCL_DKP_SRC_PTR
| OP_PCL_DKP_DST_PTR
|
536 append_ptr(desc
, adata
->key_dma
);
540 #endif /* DESC_CONSTR_H */