1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
28e8ec596SKim Phillips /*
38e8ec596SKim Phillips  * caam descriptor construction helper functions
48e8ec596SKim Phillips  *
5c4b66406SYashpal Dutta  * Copyright 2008-2012 Freescale Semiconductor, Inc.
6a5e5c133SHoria Geantă  * Copyright 2019 NXP
78e8ec596SKim Phillips  */
88e8ec596SKim Phillips 
9cd373691SHoria Geantă #ifndef DESC_CONSTR_H
10cd373691SHoria Geantă #define DESC_CONSTR_H
11cd373691SHoria Geantă 
128e8ec596SKim Phillips #include "desc.h"
13261ea058SHoria Geantă #include "regs.h"
148e8ec596SKim Phillips 
158e8ec596SKim Phillips #define IMMEDIATE (1 << 23)
168e8ec596SKim Phillips #define CAAM_CMD_SZ sizeof(u32)
171a3daadcSAndrey Smirnov #define CAAM_PTR_SZ caam_ptr_sz
181a3daadcSAndrey Smirnov #define CAAM_PTR_SZ_MAX sizeof(dma_addr_t)
191a3daadcSAndrey Smirnov #define CAAM_PTR_SZ_MIN sizeof(u32)
201acebad3SYuan Kang #define CAAM_DESC_BYTES_MAX (CAAM_CMD_SZ * MAX_CAAM_DESCSIZE)
211a3daadcSAndrey Smirnov #define __DESC_JOB_IO_LEN(n) (CAAM_CMD_SZ * 5 + (n) * 3)
221a3daadcSAndrey Smirnov #define DESC_JOB_IO_LEN __DESC_JOB_IO_LEN(CAAM_PTR_SZ)
231a3daadcSAndrey Smirnov #define DESC_JOB_IO_LEN_MAX __DESC_JOB_IO_LEN(CAAM_PTR_SZ_MAX)
241a3daadcSAndrey Smirnov #define DESC_JOB_IO_LEN_MIN __DESC_JOB_IO_LEN(CAAM_PTR_SZ_MIN)
258e8ec596SKim Phillips 
263a0944c5SAndrey Smirnov /*
273a0944c5SAndrey Smirnov  * The CAAM QI hardware constructs a job descriptor which points
283a0944c5SAndrey Smirnov  * to shared descriptor (as pointed by context_a of FQ to CAAM).
293a0944c5SAndrey Smirnov  * When the job descriptor is executed by deco, the whole job
303a0944c5SAndrey Smirnov  * descriptor together with shared descriptor gets loaded in
313a0944c5SAndrey Smirnov  * deco buffer which is 64 words long (each 32-bit).
323a0944c5SAndrey Smirnov  *
333a0944c5SAndrey Smirnov  * The job descriptor constructed by QI hardware has layout:
343a0944c5SAndrey Smirnov  *
353a0944c5SAndrey Smirnov  *	HEADER		(1 word)
363a0944c5SAndrey Smirnov  *	Shdesc ptr	(1 or 2 words)
373a0944c5SAndrey Smirnov  *	SEQ_OUT_PTR	(1 word)
383a0944c5SAndrey Smirnov  *	Out ptr		(1 or 2 words)
393a0944c5SAndrey Smirnov  *	Out length	(1 word)
403a0944c5SAndrey Smirnov  *	SEQ_IN_PTR	(1 word)
413a0944c5SAndrey Smirnov  *	In ptr		(1 or 2 words)
423a0944c5SAndrey Smirnov  *	In length	(1 word)
433a0944c5SAndrey Smirnov  *
443a0944c5SAndrey Smirnov  * The shdesc ptr is used to fetch shared descriptor contents
453a0944c5SAndrey Smirnov  * into deco buffer.
463a0944c5SAndrey Smirnov  *
473a0944c5SAndrey Smirnov  * Apart from shdesc contents, the total number of words that
483a0944c5SAndrey Smirnov  * get loaded in deco buffer are '8' or '11'. The remaining words
493a0944c5SAndrey Smirnov  * in deco buffer can be used for storing shared descriptor.
503a0944c5SAndrey Smirnov  */
511a3daadcSAndrey Smirnov #define MAX_SDLEN	((CAAM_DESC_BYTES_MAX - DESC_JOB_IO_LEN_MIN) / CAAM_CMD_SZ)
523a0944c5SAndrey Smirnov 
538e8ec596SKim Phillips #ifdef DEBUG
548e8ec596SKim Phillips #define PRINT_POS do { printk(KERN_DEBUG "%02d: %s\n", desc_len(desc),\
558e8ec596SKim Phillips 			      &__func__[sizeof("append")]); } while (0)
568e8ec596SKim Phillips #else
578e8ec596SKim Phillips #define PRINT_POS
588e8ec596SKim Phillips #endif
598e8ec596SKim Phillips 
60a2ecb155SKim Phillips #define SET_OK_NO_PROP_ERRORS (IMMEDIATE | LDST_CLASS_DECO | \
611acebad3SYuan Kang 			       LDST_SRCDST_WORD_DECOCTRL | \
62a2ecb155SKim Phillips 			       (LDOFF_CHG_SHARE_OK_NO_PROP << \
63a2ecb155SKim Phillips 				LDST_OFFSET_SHIFT))
648e8ec596SKim Phillips #define DISABLE_AUTO_INFO_FIFO (IMMEDIATE | LDST_CLASS_DECO | \
658e8ec596SKim Phillips 				LDST_SRCDST_WORD_DECOCTRL | \
668e8ec596SKim Phillips 				(LDOFF_DISABLE_AUTO_NFIFO << LDST_OFFSET_SHIFT))
678e8ec596SKim Phillips #define ENABLE_AUTO_INFO_FIFO (IMMEDIATE | LDST_CLASS_DECO | \
688e8ec596SKim Phillips 			       LDST_SRCDST_WORD_DECOCTRL | \
698e8ec596SKim Phillips 			       (LDOFF_ENABLE_AUTO_NFIFO << LDST_OFFSET_SHIFT))
708e8ec596SKim Phillips 
71261ea058SHoria Geantă extern bool caam_little_end;
721a3daadcSAndrey Smirnov extern size_t caam_ptr_sz;
73261ea058SHoria Geantă 
74a5e5c133SHoria Geantă /*
75a5e5c133SHoria Geantă  * HW fetches 4 S/G table entries at a time, irrespective of how many entries
76a5e5c133SHoria Geantă  * are in the table. It's SW's responsibility to make sure these accesses
77a5e5c133SHoria Geantă  * do not have side effects.
78a5e5c133SHoria Geantă  */
pad_sg_nents(int sg_nents)79a5e5c133SHoria Geantă static inline int pad_sg_nents(int sg_nents)
80a5e5c133SHoria Geantă {
81a5e5c133SHoria Geantă 	return ALIGN(sg_nents, 4);
82a5e5c133SHoria Geantă }
83a5e5c133SHoria Geantă 
desc_len(u32 * const desc)8424a4f14fSHoria Geantă static inline int desc_len(u32 * const desc)
858e8ec596SKim Phillips {
86261ea058SHoria Geantă 	return caam32_to_cpu(*desc) & HDR_DESCLEN_MASK;
878e8ec596SKim Phillips }
888e8ec596SKim Phillips 
desc_bytes(void * const desc)8924a4f14fSHoria Geantă static inline int desc_bytes(void * const desc)
908e8ec596SKim Phillips {
918e8ec596SKim Phillips 	return desc_len(desc) * CAAM_CMD_SZ;
928e8ec596SKim Phillips }
938e8ec596SKim Phillips 
desc_end(u32 * const desc)9424a4f14fSHoria Geantă static inline u32 *desc_end(u32 * const desc)
958e8ec596SKim Phillips {
968e8ec596SKim Phillips 	return desc + desc_len(desc);
978e8ec596SKim Phillips }
988e8ec596SKim Phillips 
sh_desc_pdb(u32 * const desc)9924a4f14fSHoria Geantă static inline void *sh_desc_pdb(u32 * const desc)
1008e8ec596SKim Phillips {
1018e8ec596SKim Phillips 	return desc + 1;
1028e8ec596SKim Phillips }
1038e8ec596SKim Phillips 
init_desc(u32 * const desc,u32 options)10424a4f14fSHoria Geantă static inline void init_desc(u32 * const desc, u32 options)
1058e8ec596SKim Phillips {
106261ea058SHoria Geantă 	*desc = cpu_to_caam32((options | HDR_ONE) + 1);
1078e8ec596SKim Phillips }
1088e8ec596SKim Phillips 
init_sh_desc(u32 * const desc,u32 options)10924a4f14fSHoria Geantă static inline void init_sh_desc(u32 * const desc, u32 options)
1108e8ec596SKim Phillips {
1118e8ec596SKim Phillips 	PRINT_POS;
1128e8ec596SKim Phillips 	init_desc(desc, CMD_SHARED_DESC_HDR | options);
1138e8ec596SKim Phillips }
1148e8ec596SKim Phillips 
init_sh_desc_pdb(u32 * const desc,u32 options,size_t pdb_bytes)11524a4f14fSHoria Geantă static inline void init_sh_desc_pdb(u32 * const desc, u32 options,
11624a4f14fSHoria Geantă 				    size_t pdb_bytes)
1178e8ec596SKim Phillips {
118991c569cSKim Phillips 	u32 pdb_len = (pdb_bytes + CAAM_CMD_SZ - 1) / CAAM_CMD_SZ;
1198e8ec596SKim Phillips 
120c4b66406SYashpal Dutta 	init_sh_desc(desc, (((pdb_len + 1) << HDR_START_IDX_SHIFT) + pdb_len) |
1218e8ec596SKim Phillips 		     options);
1228e8ec596SKim Phillips }
1238e8ec596SKim Phillips 
init_job_desc(u32 * const desc,u32 options)12424a4f14fSHoria Geantă static inline void init_job_desc(u32 * const desc, u32 options)
1258e8ec596SKim Phillips {
1268e8ec596SKim Phillips 	init_desc(desc, CMD_DESC_HDR | options);
1278e8ec596SKim Phillips }
1288e8ec596SKim Phillips 
init_job_desc_pdb(u32 * const desc,u32 options,size_t pdb_bytes)12924a4f14fSHoria Geantă static inline void init_job_desc_pdb(u32 * const desc, u32 options,
13024a4f14fSHoria Geantă 				     size_t pdb_bytes)
1318c419778STudor Ambarus {
1328c419778STudor Ambarus 	u32 pdb_len = (pdb_bytes + CAAM_CMD_SZ - 1) / CAAM_CMD_SZ;
1338c419778STudor Ambarus 
1348c419778STudor Ambarus 	init_job_desc(desc, (((pdb_len + 1) << HDR_START_IDX_SHIFT)) | options);
1358c419778STudor Ambarus }
1368c419778STudor Ambarus 
append_ptr(u32 * const desc,dma_addr_t ptr)13724a4f14fSHoria Geantă static inline void append_ptr(u32 * const desc, dma_addr_t ptr)
1388e8ec596SKim Phillips {
139a1cf573eSAndrey Smirnov 	if (caam_ptr_sz == sizeof(dma_addr_t)) {
1408e8ec596SKim Phillips 		dma_addr_t *offset = (dma_addr_t *)desc_end(desc);
1418e8ec596SKim Phillips 
142261ea058SHoria Geantă 		*offset = cpu_to_caam_dma(ptr);
143a1cf573eSAndrey Smirnov 	} else {
144a1cf573eSAndrey Smirnov 		u32 *offset = (u32 *)desc_end(desc);
145a1cf573eSAndrey Smirnov 
146a1cf573eSAndrey Smirnov 		*offset = cpu_to_caam_dma(ptr);
147a1cf573eSAndrey Smirnov 	}
1488e8ec596SKim Phillips 
149261ea058SHoria Geantă 	(*desc) = cpu_to_caam32(caam32_to_cpu(*desc) +
150261ea058SHoria Geantă 				CAAM_PTR_SZ / CAAM_CMD_SZ);
1518e8ec596SKim Phillips }
1528e8ec596SKim Phillips 
init_job_desc_shared(u32 * const desc,dma_addr_t ptr,int len,u32 options)15324a4f14fSHoria Geantă static inline void init_job_desc_shared(u32 * const desc, dma_addr_t ptr,
15424a4f14fSHoria Geantă 					int len, u32 options)
1558e8ec596SKim Phillips {
1568e8ec596SKim Phillips 	PRINT_POS;
1578e8ec596SKim Phillips 	init_job_desc(desc, HDR_SHARED | options |
1588e8ec596SKim Phillips 		      (len << HDR_START_IDX_SHIFT));
1598e8ec596SKim Phillips 	append_ptr(desc, ptr);
1608e8ec596SKim Phillips }
1618e8ec596SKim Phillips 
append_data(u32 * const desc,const void * data,int len)1626674a4fdSHoria Geantă static inline void append_data(u32 * const desc, const void *data, int len)
1638e8ec596SKim Phillips {
1648e8ec596SKim Phillips 	u32 *offset = desc_end(desc);
1658e8ec596SKim Phillips 
166*4f289826SHerbert Xu 	/* Avoid gcc warning: memcpy with data == NULL */
167*4f289826SHerbert Xu 	if (!IS_ENABLED(CONFIG_CRYPTO_DEV_FSL_CAAM_DEBUG) || data)
1688e8ec596SKim Phillips 		memcpy(offset, data, len);
1698e8ec596SKim Phillips 
170261ea058SHoria Geantă 	(*desc) = cpu_to_caam32(caam32_to_cpu(*desc) +
171261ea058SHoria Geantă 				(len + CAAM_CMD_SZ - 1) / CAAM_CMD_SZ);
1728e8ec596SKim Phillips }
1738e8ec596SKim Phillips 
append_cmd(u32 * const desc,u32 command)17424a4f14fSHoria Geantă static inline void append_cmd(u32 * const desc, u32 command)
1758e8ec596SKim Phillips {
1768e8ec596SKim Phillips 	u32 *cmd = desc_end(desc);
1778e8ec596SKim Phillips 
178261ea058SHoria Geantă 	*cmd = cpu_to_caam32(command);
1798e8ec596SKim Phillips 
180261ea058SHoria Geantă 	(*desc) = cpu_to_caam32(caam32_to_cpu(*desc) + 1);
1818e8ec596SKim Phillips }
1828e8ec596SKim Phillips 
1833ebfa92fSAndrei Varvara #define append_u32 append_cmd
1843ebfa92fSAndrei Varvara 
append_u64(u32 * const desc,u64 data)18524a4f14fSHoria Geantă static inline void append_u64(u32 * const desc, u64 data)
1863ebfa92fSAndrei Varvara {
1873ebfa92fSAndrei Varvara 	u32 *offset = desc_end(desc);
1883ebfa92fSAndrei Varvara 
189261ea058SHoria Geantă 	/* Only 32-bit alignment is guaranteed in descriptor buffer */
190261ea058SHoria Geantă 	if (caam_little_end) {
191261ea058SHoria Geantă 		*offset = cpu_to_caam32(lower_32_bits(data));
192261ea058SHoria Geantă 		*(++offset) = cpu_to_caam32(upper_32_bits(data));
193261ea058SHoria Geantă 	} else {
194261ea058SHoria Geantă 		*offset = cpu_to_caam32(upper_32_bits(data));
195261ea058SHoria Geantă 		*(++offset) = cpu_to_caam32(lower_32_bits(data));
196261ea058SHoria Geantă 	}
1973ebfa92fSAndrei Varvara 
198261ea058SHoria Geantă 	(*desc) = cpu_to_caam32(caam32_to_cpu(*desc) + 2);
1993ebfa92fSAndrei Varvara }
2003ebfa92fSAndrei Varvara 
2013ebfa92fSAndrei Varvara /* Write command without affecting header, and return pointer to next word */
write_cmd(u32 * const desc,u32 command)20224a4f14fSHoria Geantă static inline u32 *write_cmd(u32 * const desc, u32 command)
2033ebfa92fSAndrei Varvara {
204261ea058SHoria Geantă 	*desc = cpu_to_caam32(command);
2053ebfa92fSAndrei Varvara 
2063ebfa92fSAndrei Varvara 	return desc + 1;
2073ebfa92fSAndrei Varvara }
2083ebfa92fSAndrei Varvara 
append_cmd_ptr(u32 * const desc,dma_addr_t ptr,int len,u32 command)20924a4f14fSHoria Geantă static inline void append_cmd_ptr(u32 * const desc, dma_addr_t ptr, int len,
2108e8ec596SKim Phillips 				  u32 command)
2118e8ec596SKim Phillips {
2128e8ec596SKim Phillips 	append_cmd(desc, command | len);
2138e8ec596SKim Phillips 	append_ptr(desc, ptr);
2148e8ec596SKim Phillips }
2158e8ec596SKim Phillips 
2166ec47334SYuan Kang /* Write length after pointer, rather than inside command */
append_cmd_ptr_extlen(u32 * const desc,dma_addr_t ptr,unsigned int len,u32 command)21724a4f14fSHoria Geantă static inline void append_cmd_ptr_extlen(u32 * const desc, dma_addr_t ptr,
2186ec47334SYuan Kang 					 unsigned int len, u32 command)
2196ec47334SYuan Kang {
2206ec47334SYuan Kang 	append_cmd(desc, command);
221e2d4ea94SAndrei Varvara 	if (!(command & (SQIN_RTO | SQIN_PRE)))
2226ec47334SYuan Kang 		append_ptr(desc, ptr);
2236ec47334SYuan Kang 	append_cmd(desc, len);
2246ec47334SYuan Kang }
2256ec47334SYuan Kang 
append_cmd_data(u32 * const desc,const void * data,int len,u32 command)2266674a4fdSHoria Geantă static inline void append_cmd_data(u32 * const desc, const void *data, int len,
2278e8ec596SKim Phillips 				   u32 command)
2288e8ec596SKim Phillips {
2298e8ec596SKim Phillips 	append_cmd(desc, command | IMMEDIATE | len);
2308e8ec596SKim Phillips 	append_data(desc, data, len);
2318e8ec596SKim Phillips }
2328e8ec596SKim Phillips 
233ae4a825fSHoria Geanta #define APPEND_CMD_RET(cmd, op) \
23424a4f14fSHoria Geantă static inline u32 *append_##cmd(u32 * const desc, u32 options) \
235ae4a825fSHoria Geanta { \
236ae4a825fSHoria Geanta 	u32 *cmd = desc_end(desc); \
237ae4a825fSHoria Geanta 	PRINT_POS; \
238ae4a825fSHoria Geanta 	append_cmd(desc, CMD_##op | options); \
239ae4a825fSHoria Geanta 	return cmd; \
2408e8ec596SKim Phillips }
APPEND_CMD_RET(jump,JUMP)241ae4a825fSHoria Geanta APPEND_CMD_RET(jump, JUMP)
242ae4a825fSHoria Geanta APPEND_CMD_RET(move, MOVE)
243d6bbd4eeSHoria Geantă APPEND_CMD_RET(move_len, MOVE_LEN)
2448e8ec596SKim Phillips 
24524a4f14fSHoria Geantă static inline void set_jump_tgt_here(u32 * const desc, u32 *jump_cmd)
2468e8ec596SKim Phillips {
247261ea058SHoria Geantă 	*jump_cmd = cpu_to_caam32(caam32_to_cpu(*jump_cmd) |
248261ea058SHoria Geantă 				  (desc_len(desc) - (jump_cmd - desc)));
2498e8ec596SKim Phillips }
2508e8ec596SKim Phillips 
set_move_tgt_here(u32 * const desc,u32 * move_cmd)25124a4f14fSHoria Geantă static inline void set_move_tgt_here(u32 * const desc, u32 *move_cmd)
252ae4a825fSHoria Geanta {
253261ea058SHoria Geantă 	u32 val = caam32_to_cpu(*move_cmd);
254261ea058SHoria Geantă 
255261ea058SHoria Geantă 	val &= ~MOVE_OFFSET_MASK;
256261ea058SHoria Geantă 	val |= (desc_len(desc) << (MOVE_OFFSET_SHIFT + 2)) & MOVE_OFFSET_MASK;
257261ea058SHoria Geantă 	*move_cmd = cpu_to_caam32(val);
258ae4a825fSHoria Geanta }
259ae4a825fSHoria Geanta 
2608e8ec596SKim Phillips #define APPEND_CMD(cmd, op) \
26124a4f14fSHoria Geantă static inline void append_##cmd(u32 * const desc, u32 options) \
2628e8ec596SKim Phillips { \
2638e8ec596SKim Phillips 	PRINT_POS; \
2648e8ec596SKim Phillips 	append_cmd(desc, CMD_##op | options); \
2658e8ec596SKim Phillips }
APPEND_CMD(operation,OPERATION)2668e8ec596SKim Phillips APPEND_CMD(operation, OPERATION)
2678e8ec596SKim Phillips 
2688e8ec596SKim Phillips #define APPEND_CMD_LEN(cmd, op) \
26924a4f14fSHoria Geantă static inline void append_##cmd(u32 * const desc, unsigned int len, \
27024a4f14fSHoria Geantă 				u32 options) \
2718e8ec596SKim Phillips { \
2728e8ec596SKim Phillips 	PRINT_POS; \
2738e8ec596SKim Phillips 	append_cmd(desc, CMD_##op | len | options); \
2748e8ec596SKim Phillips }
2752b22f6c5SCatalin Vasile 
2762b22f6c5SCatalin Vasile APPEND_CMD_LEN(seq_load, SEQ_LOAD)
2778e8ec596SKim Phillips APPEND_CMD_LEN(seq_store, SEQ_STORE)
2788e8ec596SKim Phillips APPEND_CMD_LEN(seq_fifo_load, SEQ_FIFO_LOAD)
2798e8ec596SKim Phillips APPEND_CMD_LEN(seq_fifo_store, SEQ_FIFO_STORE)
2808e8ec596SKim Phillips 
2818e8ec596SKim Phillips #define APPEND_CMD_PTR(cmd, op) \
28224a4f14fSHoria Geantă static inline void append_##cmd(u32 * const desc, dma_addr_t ptr, \
28324a4f14fSHoria Geantă 				unsigned int len, u32 options) \
2848e8ec596SKim Phillips { \
2858e8ec596SKim Phillips 	PRINT_POS; \
2868e8ec596SKim Phillips 	append_cmd_ptr(desc, ptr, len, CMD_##op | options); \
2878e8ec596SKim Phillips }
2888e8ec596SKim Phillips APPEND_CMD_PTR(key, KEY)
2898e8ec596SKim Phillips APPEND_CMD_PTR(load, LOAD)
2908e8ec596SKim Phillips APPEND_CMD_PTR(fifo_load, FIFO_LOAD)
2918e8ec596SKim Phillips APPEND_CMD_PTR(fifo_store, FIFO_STORE)
2928e8ec596SKim Phillips 
29324a4f14fSHoria Geantă static inline void append_store(u32 * const desc, dma_addr_t ptr,
29424a4f14fSHoria Geantă 				unsigned int len, u32 options)
295524f1bd9SAndrei Varvara {
296524f1bd9SAndrei Varvara 	u32 cmd_src;
297524f1bd9SAndrei Varvara 
298524f1bd9SAndrei Varvara 	cmd_src = options & LDST_SRCDST_MASK;
299524f1bd9SAndrei Varvara 
300524f1bd9SAndrei Varvara 	append_cmd(desc, CMD_STORE | options | len);
301524f1bd9SAndrei Varvara 
302524f1bd9SAndrei Varvara 	/* The following options do not require pointer */
303524f1bd9SAndrei Varvara 	if (!(cmd_src == LDST_SRCDST_WORD_DESCBUF_SHARED ||
304524f1bd9SAndrei Varvara 	      cmd_src == LDST_SRCDST_WORD_DESCBUF_JOB    ||
305524f1bd9SAndrei Varvara 	      cmd_src == LDST_SRCDST_WORD_DESCBUF_JOB_WE ||
306524f1bd9SAndrei Varvara 	      cmd_src == LDST_SRCDST_WORD_DESCBUF_SHARED_WE))
307524f1bd9SAndrei Varvara 		append_ptr(desc, ptr);
308524f1bd9SAndrei Varvara }
309524f1bd9SAndrei Varvara 
3106ec47334SYuan Kang #define APPEND_SEQ_PTR_INTLEN(cmd, op) \
31124a4f14fSHoria Geantă static inline void append_seq_##cmd##_ptr_intlen(u32 * const desc, \
31224a4f14fSHoria Geantă 						 dma_addr_t ptr, \
3136ec47334SYuan Kang 						 unsigned int len, \
3146ec47334SYuan Kang 						 u32 options) \
3156ec47334SYuan Kang { \
3166ec47334SYuan Kang 	PRINT_POS; \
317e2d4ea94SAndrei Varvara 	if (options & (SQIN_RTO | SQIN_PRE)) \
318e2d4ea94SAndrei Varvara 		append_cmd(desc, CMD_SEQ_##op##_PTR | len | options); \
319e2d4ea94SAndrei Varvara 	else \
3206ec47334SYuan Kang 		append_cmd_ptr(desc, ptr, len, CMD_SEQ_##op##_PTR | options); \
3216ec47334SYuan Kang }
3226ec47334SYuan Kang APPEND_SEQ_PTR_INTLEN(in, IN)
3236ec47334SYuan Kang APPEND_SEQ_PTR_INTLEN(out, OUT)
3246ec47334SYuan Kang 
3258e8ec596SKim Phillips #define APPEND_CMD_PTR_TO_IMM(cmd, op) \
3266674a4fdSHoria Geantă static inline void append_##cmd##_as_imm(u32 * const desc, const void *data, \
3278e8ec596SKim Phillips 					 unsigned int len, u32 options) \
3288e8ec596SKim Phillips { \
3298e8ec596SKim Phillips 	PRINT_POS; \
3308e8ec596SKim Phillips 	append_cmd_data(desc, data, len, CMD_##op | options); \
3318e8ec596SKim Phillips }
3328e8ec596SKim Phillips APPEND_CMD_PTR_TO_IMM(load, LOAD);
3338e8ec596SKim Phillips APPEND_CMD_PTR_TO_IMM(fifo_load, FIFO_LOAD);
3348e8ec596SKim Phillips 
3356ec47334SYuan Kang #define APPEND_CMD_PTR_EXTLEN(cmd, op) \
33624a4f14fSHoria Geantă static inline void append_##cmd##_extlen(u32 * const desc, dma_addr_t ptr, \
3376ec47334SYuan Kang 					 unsigned int len, u32 options) \
3386ec47334SYuan Kang { \
3396ec47334SYuan Kang 	PRINT_POS; \
3406ec47334SYuan Kang 	append_cmd_ptr_extlen(desc, ptr, len, CMD_##op | SQIN_EXT | options); \
3416ec47334SYuan Kang }
3426ec47334SYuan Kang APPEND_CMD_PTR_EXTLEN(seq_in_ptr, SEQ_IN_PTR)
3436ec47334SYuan Kang APPEND_CMD_PTR_EXTLEN(seq_out_ptr, SEQ_OUT_PTR)
3446ec47334SYuan Kang 
3456ec47334SYuan Kang /*
3466ec47334SYuan Kang  * Determine whether to store length internally or externally depending on
3476ec47334SYuan Kang  * the size of its type
3486ec47334SYuan Kang  */
3496ec47334SYuan Kang #define APPEND_CMD_PTR_LEN(cmd, op, type) \
35024a4f14fSHoria Geantă static inline void append_##cmd(u32 * const desc, dma_addr_t ptr, \
3516ec47334SYuan Kang 				type len, u32 options) \
3526ec47334SYuan Kang { \
3536ec47334SYuan Kang 	PRINT_POS; \
3546ec47334SYuan Kang 	if (sizeof(type) > sizeof(u16)) \
3556ec47334SYuan Kang 		append_##cmd##_extlen(desc, ptr, len, options); \
3566ec47334SYuan Kang 	else \
3576ec47334SYuan Kang 		append_##cmd##_intlen(desc, ptr, len, options); \
3586ec47334SYuan Kang }
3596ec47334SYuan Kang APPEND_CMD_PTR_LEN(seq_in_ptr, SEQ_IN_PTR, u32)
3606ec47334SYuan Kang APPEND_CMD_PTR_LEN(seq_out_ptr, SEQ_OUT_PTR, u32)
3616ec47334SYuan Kang 
3628e8ec596SKim Phillips /*
3638e8ec596SKim Phillips  * 2nd variant for commands whose specified immediate length differs
3648e8ec596SKim Phillips  * from length of immediate data provided, e.g., split keys
3658e8ec596SKim Phillips  */
3668e8ec596SKim Phillips #define APPEND_CMD_PTR_TO_IMM2(cmd, op) \
3676674a4fdSHoria Geantă static inline void append_##cmd##_as_imm(u32 * const desc, const void *data, \
3688e8ec596SKim Phillips 					 unsigned int data_len, \
3698e8ec596SKim Phillips 					 unsigned int len, u32 options) \
3708e8ec596SKim Phillips { \
3718e8ec596SKim Phillips 	PRINT_POS; \
3728e8ec596SKim Phillips 	append_cmd(desc, CMD_##op | IMMEDIATE | len | options); \
3738e8ec596SKim Phillips 	append_data(desc, data, data_len); \
3748e8ec596SKim Phillips }
3758e8ec596SKim Phillips APPEND_CMD_PTR_TO_IMM2(key, KEY);
3768e8ec596SKim Phillips 
3778e8ec596SKim Phillips #define APPEND_CMD_RAW_IMM(cmd, op, type) \
37824a4f14fSHoria Geantă static inline void append_##cmd##_imm_##type(u32 * const desc, type immediate, \
3798e8ec596SKim Phillips 					     u32 options) \
3808e8ec596SKim Phillips { \
3818e8ec596SKim Phillips 	PRINT_POS; \
382d6bbd4eeSHoria Geantă 	if (options & LDST_LEN_MASK) \
383d6bbd4eeSHoria Geantă 		append_cmd(desc, CMD_##op | IMMEDIATE | options); \
384d6bbd4eeSHoria Geantă 	else \
385d6bbd4eeSHoria Geantă 		append_cmd(desc, CMD_##op | IMMEDIATE | options | \
386d6bbd4eeSHoria Geantă 			   sizeof(type)); \
3878e8ec596SKim Phillips 	append_cmd(desc, immediate); \
3888e8ec596SKim Phillips }
3898e8ec596SKim Phillips APPEND_CMD_RAW_IMM(load, LOAD, u32);
3901acebad3SYuan Kang 
3911acebad3SYuan Kang /*
3925ba1c7b5SCatalin Vasile  * ee - endianness
3935ba1c7b5SCatalin Vasile  * size - size of immediate type in bytes
3945ba1c7b5SCatalin Vasile  */
3955ba1c7b5SCatalin Vasile #define APPEND_CMD_RAW_IMM2(cmd, op, ee, size) \
3965ba1c7b5SCatalin Vasile static inline void append_##cmd##_imm_##ee##size(u32 *desc, \
3975ba1c7b5SCatalin Vasile 						   u##size immediate, \
3985ba1c7b5SCatalin Vasile 						   u32 options) \
3995ba1c7b5SCatalin Vasile { \
4005ba1c7b5SCatalin Vasile 	__##ee##size data = cpu_to_##ee##size(immediate); \
4015ba1c7b5SCatalin Vasile 	PRINT_POS; \
4025ba1c7b5SCatalin Vasile 	append_cmd(desc, CMD_##op | IMMEDIATE | options | sizeof(data)); \
4035ba1c7b5SCatalin Vasile 	append_data(desc, &data, sizeof(data)); \
4045ba1c7b5SCatalin Vasile }
4055ba1c7b5SCatalin Vasile 
4065ba1c7b5SCatalin Vasile APPEND_CMD_RAW_IMM2(load, LOAD, be, 32);
4075ba1c7b5SCatalin Vasile 
4085ba1c7b5SCatalin Vasile /*
4091acebad3SYuan Kang  * Append math command. Only the last part of destination and source need to
4101acebad3SYuan Kang  * be specified
4111acebad3SYuan Kang  */
4121acebad3SYuan Kang #define APPEND_MATH(op, desc, dest, src_0, src_1, len) \
4131acebad3SYuan Kang append_cmd(desc, CMD_MATH | MATH_FUN_##op | MATH_DEST_##dest | \
4143ebfa92fSAndrei Varvara 	MATH_SRC0_##src_0 | MATH_SRC1_##src_1 | (u32)len);
4151acebad3SYuan Kang 
4161acebad3SYuan Kang #define append_math_add(desc, dest, src0, src1, len) \
4171acebad3SYuan Kang 	APPEND_MATH(ADD, desc, dest, src0, src1, len)
4181acebad3SYuan Kang #define append_math_sub(desc, dest, src0, src1, len) \
4191acebad3SYuan Kang 	APPEND_MATH(SUB, desc, dest, src0, src1, len)
4201acebad3SYuan Kang #define append_math_add_c(desc, dest, src0, src1, len) \
4211acebad3SYuan Kang 	APPEND_MATH(ADDC, desc, dest, src0, src1, len)
4221acebad3SYuan Kang #define append_math_sub_b(desc, dest, src0, src1, len) \
4231acebad3SYuan Kang 	APPEND_MATH(SUBB, desc, dest, src0, src1, len)
4241acebad3SYuan Kang #define append_math_and(desc, dest, src0, src1, len) \
4251acebad3SYuan Kang 	APPEND_MATH(AND, desc, dest, src0, src1, len)
4261acebad3SYuan Kang #define append_math_or(desc, dest, src0, src1, len) \
4271acebad3SYuan Kang 	APPEND_MATH(OR, desc, dest, src0, src1, len)
4281acebad3SYuan Kang #define append_math_xor(desc, dest, src0, src1, len) \
4291acebad3SYuan Kang 	APPEND_MATH(XOR, desc, dest, src0, src1, len)
4301acebad3SYuan Kang #define append_math_lshift(desc, dest, src0, src1, len) \
4311acebad3SYuan Kang 	APPEND_MATH(LSHIFT, desc, dest, src0, src1, len)
4321acebad3SYuan Kang #define append_math_rshift(desc, dest, src0, src1, len) \
4331acebad3SYuan Kang 	APPEND_MATH(RSHIFT, desc, dest, src0, src1, len)
434d179333bSAndrei Varvara #define append_math_ldshift(desc, dest, src0, src1, len) \
435d179333bSAndrei Varvara 	APPEND_MATH(SHLD, desc, dest, src0, src1, len)
4361acebad3SYuan Kang 
4371acebad3SYuan Kang /* Exactly one source is IMM. Data is passed in as u32 value */
4381acebad3SYuan Kang #define APPEND_MATH_IMM_u32(op, desc, dest, src_0, src_1, data) \
4391acebad3SYuan Kang do { \
4401acebad3SYuan Kang 	APPEND_MATH(op, desc, dest, src_0, src_1, CAAM_CMD_SZ); \
4411acebad3SYuan Kang 	append_cmd(desc, data); \
442ae4a825fSHoria Geanta } while (0)
4431acebad3SYuan Kang 
4441acebad3SYuan Kang #define append_math_add_imm_u32(desc, dest, src0, src1, data) \
4451acebad3SYuan Kang 	APPEND_MATH_IMM_u32(ADD, desc, dest, src0, src1, data)
4461acebad3SYuan Kang #define append_math_sub_imm_u32(desc, dest, src0, src1, data) \
4471acebad3SYuan Kang 	APPEND_MATH_IMM_u32(SUB, desc, dest, src0, src1, data)
4481acebad3SYuan Kang #define append_math_add_c_imm_u32(desc, dest, src0, src1, data) \
4491acebad3SYuan Kang 	APPEND_MATH_IMM_u32(ADDC, desc, dest, src0, src1, data)
4501acebad3SYuan Kang #define append_math_sub_b_imm_u32(desc, dest, src0, src1, data) \
4511acebad3SYuan Kang 	APPEND_MATH_IMM_u32(SUBB, desc, dest, src0, src1, data)
4521acebad3SYuan Kang #define append_math_and_imm_u32(desc, dest, src0, src1, data) \
4531acebad3SYuan Kang 	APPEND_MATH_IMM_u32(AND, desc, dest, src0, src1, data)
4541acebad3SYuan Kang #define append_math_or_imm_u32(desc, dest, src0, src1, data) \
4551acebad3SYuan Kang 	APPEND_MATH_IMM_u32(OR, desc, dest, src0, src1, data)
4561acebad3SYuan Kang #define append_math_xor_imm_u32(desc, dest, src0, src1, data) \
4571acebad3SYuan Kang 	APPEND_MATH_IMM_u32(XOR, desc, dest, src0, src1, data)
4581acebad3SYuan Kang #define append_math_lshift_imm_u32(desc, dest, src0, src1, data) \
4591acebad3SYuan Kang 	APPEND_MATH_IMM_u32(LSHIFT, desc, dest, src0, src1, data)
4601acebad3SYuan Kang #define append_math_rshift_imm_u32(desc, dest, src0, src1, data) \
4611acebad3SYuan Kang 	APPEND_MATH_IMM_u32(RSHIFT, desc, dest, src0, src1, data)
4623ebfa92fSAndrei Varvara 
4633ebfa92fSAndrei Varvara /* Exactly one source is IMM. Data is passed in as u64 value */
4643ebfa92fSAndrei Varvara #define APPEND_MATH_IMM_u64(op, desc, dest, src_0, src_1, data) \
4653ebfa92fSAndrei Varvara do { \
4663ebfa92fSAndrei Varvara 	u32 upper = (data >> 16) >> 16; \
4673ebfa92fSAndrei Varvara 	APPEND_MATH(op, desc, dest, src_0, src_1, CAAM_CMD_SZ * 2 | \
4683ebfa92fSAndrei Varvara 		    (upper ? 0 : MATH_IFB)); \
4693ebfa92fSAndrei Varvara 	if (upper) \
4703ebfa92fSAndrei Varvara 		append_u64(desc, data); \
4713ebfa92fSAndrei Varvara 	else \
472c1f2cd21STudor Ambarus 		append_u32(desc, lower_32_bits(data)); \
4733ebfa92fSAndrei Varvara } while (0)
4743ebfa92fSAndrei Varvara 
4753ebfa92fSAndrei Varvara #define append_math_add_imm_u64(desc, dest, src0, src1, data) \
4763ebfa92fSAndrei Varvara 	APPEND_MATH_IMM_u64(ADD, desc, dest, src0, src1, data)
4773ebfa92fSAndrei Varvara #define append_math_sub_imm_u64(desc, dest, src0, src1, data) \
4783ebfa92fSAndrei Varvara 	APPEND_MATH_IMM_u64(SUB, desc, dest, src0, src1, data)
4793ebfa92fSAndrei Varvara #define append_math_add_c_imm_u64(desc, dest, src0, src1, data) \
4803ebfa92fSAndrei Varvara 	APPEND_MATH_IMM_u64(ADDC, desc, dest, src0, src1, data)
4813ebfa92fSAndrei Varvara #define append_math_sub_b_imm_u64(desc, dest, src0, src1, data) \
4823ebfa92fSAndrei Varvara 	APPEND_MATH_IMM_u64(SUBB, desc, dest, src0, src1, data)
4833ebfa92fSAndrei Varvara #define append_math_and_imm_u64(desc, dest, src0, src1, data) \
4843ebfa92fSAndrei Varvara 	APPEND_MATH_IMM_u64(AND, desc, dest, src0, src1, data)
4853ebfa92fSAndrei Varvara #define append_math_or_imm_u64(desc, dest, src0, src1, data) \
4863ebfa92fSAndrei Varvara 	APPEND_MATH_IMM_u64(OR, desc, dest, src0, src1, data)
4873ebfa92fSAndrei Varvara #define append_math_xor_imm_u64(desc, dest, src0, src1, data) \
4883ebfa92fSAndrei Varvara 	APPEND_MATH_IMM_u64(XOR, desc, dest, src0, src1, data)
4893ebfa92fSAndrei Varvara #define append_math_lshift_imm_u64(desc, dest, src0, src1, data) \
4903ebfa92fSAndrei Varvara 	APPEND_MATH_IMM_u64(LSHIFT, desc, dest, src0, src1, data)
4913ebfa92fSAndrei Varvara #define append_math_rshift_imm_u64(desc, dest, src0, src1, data) \
4923ebfa92fSAndrei Varvara 	APPEND_MATH_IMM_u64(RSHIFT, desc, dest, src0, src1, data)
493db57656bSHoria Geantă 
494db57656bSHoria Geantă /**
495db57656bSHoria Geantă  * struct alginfo - Container for algorithm details
496db57656bSHoria Geantă  * @algtype: algorithm selector; for valid values, see documentation of the
497db57656bSHoria Geantă  *           functions where it is used.
498db57656bSHoria Geantă  * @keylen: length of the provided algorithm key, in bytes
499db57656bSHoria Geantă  * @keylen_pad: padded length of the provided algorithm key, in bytes
500a2fb864cSHoria Geantă  * @key_dma: dma (bus) address where algorithm key resides
501a2fb864cSHoria Geantă  * @key_virt: virtual address where algorithm key resides
502db57656bSHoria Geantă  * @key_inline: true - key can be inlined in the descriptor; false - key is
503db57656bSHoria Geantă  *              referenced by the descriptor
504db57656bSHoria Geantă  */
505db57656bSHoria Geantă struct alginfo {
506db57656bSHoria Geantă 	u32 algtype;
507db57656bSHoria Geantă 	unsigned int keylen;
508db57656bSHoria Geantă 	unsigned int keylen_pad;
5099c0bc511SArnd Bergmann 	dma_addr_t key_dma;
5106674a4fdSHoria Geantă 	const void *key_virt;
511db57656bSHoria Geantă 	bool key_inline;
512db57656bSHoria Geantă };
5134cbe79ccSHoria Geantă 
5144cbe79ccSHoria Geantă /**
5154cbe79ccSHoria Geantă  * desc_inline_query() - Provide indications on which data items can be inlined
5164cbe79ccSHoria Geantă  *                       and which shall be referenced in a shared descriptor.
5174cbe79ccSHoria Geantă  * @sd_base_len: Shared descriptor base length - bytes consumed by the commands,
5184cbe79ccSHoria Geantă  *               excluding the data items to be inlined (or corresponding
5194cbe79ccSHoria Geantă  *               pointer if an item is not inlined). Each cnstr_* function that
5204cbe79ccSHoria Geantă  *               generates descriptors should have a define mentioning
5214cbe79ccSHoria Geantă  *               corresponding length.
5224cbe79ccSHoria Geantă  * @jd_len: Maximum length of the job descriptor(s) that will be used
5234cbe79ccSHoria Geantă  *          together with the shared descriptor.
5244cbe79ccSHoria Geantă  * @data_len: Array of lengths of the data items trying to be inlined
5254cbe79ccSHoria Geantă  * @inl_mask: 32bit mask with bit x = 1 if data item x can be inlined, 0
5264cbe79ccSHoria Geantă  *            otherwise.
5274cbe79ccSHoria Geantă  * @count: Number of data items (size of @data_len array); must be <= 32
5284cbe79ccSHoria Geantă  *
5294cbe79ccSHoria Geantă  * Return: 0 if data can be inlined / referenced, negative value if not. If 0,
5304cbe79ccSHoria Geantă  *         check @inl_mask for details.
5314cbe79ccSHoria Geantă  */
desc_inline_query(unsigned int sd_base_len,unsigned int jd_len,unsigned int * data_len,u32 * inl_mask,unsigned int count)5324cbe79ccSHoria Geantă static inline int desc_inline_query(unsigned int sd_base_len,
5334cbe79ccSHoria Geantă 				    unsigned int jd_len, unsigned int *data_len,
5344cbe79ccSHoria Geantă 				    u32 *inl_mask, unsigned int count)
5354cbe79ccSHoria Geantă {
5364cbe79ccSHoria Geantă 	int rem_bytes = (int)(CAAM_DESC_BYTES_MAX - sd_base_len - jd_len);
5374cbe79ccSHoria Geantă 	unsigned int i;
5384cbe79ccSHoria Geantă 
5394cbe79ccSHoria Geantă 	*inl_mask = 0;
5404cbe79ccSHoria Geantă 	for (i = 0; (i < count) && (rem_bytes > 0); i++) {
5414cbe79ccSHoria Geantă 		if (rem_bytes - (int)(data_len[i] +
5424cbe79ccSHoria Geantă 			(count - i - 1) * CAAM_PTR_SZ) >= 0) {
5434cbe79ccSHoria Geantă 			rem_bytes -= data_len[i];
5444cbe79ccSHoria Geantă 			*inl_mask |= (1 << i);
5454cbe79ccSHoria Geantă 		} else {
5464cbe79ccSHoria Geantă 			rem_bytes -= CAAM_PTR_SZ;
5474cbe79ccSHoria Geantă 		}
5484cbe79ccSHoria Geantă 	}
5494cbe79ccSHoria Geantă 
5504cbe79ccSHoria Geantă 	return (rem_bytes >= 0) ? 0 : -1;
5514cbe79ccSHoria Geantă }
552cd373691SHoria Geantă 
5537e0880b9SHoria Geantă /**
5547e0880b9SHoria Geantă  * append_proto_dkp - Derived Key Protocol (DKP): key -> split key
5557e0880b9SHoria Geantă  * @desc: pointer to buffer used for descriptor construction
5567e0880b9SHoria Geantă  * @adata: pointer to authentication transform definitions.
5577e0880b9SHoria Geantă  *         keylen should be the length of initial key, while keylen_pad
5587e0880b9SHoria Geantă  *         the length of the derived (split) key.
5597e0880b9SHoria Geantă  *         Valid algorithm values - one of OP_ALG_ALGSEL_{MD5, SHA1, SHA224,
5607e0880b9SHoria Geantă  *         SHA256, SHA384, SHA512}.
5617e0880b9SHoria Geantă  */
append_proto_dkp(u32 * const desc,struct alginfo * adata)5627e0880b9SHoria Geantă static inline void append_proto_dkp(u32 * const desc, struct alginfo *adata)
5637e0880b9SHoria Geantă {
5647e0880b9SHoria Geantă 	u32 protid;
5657e0880b9SHoria Geantă 
5667e0880b9SHoria Geantă 	/*
5677e0880b9SHoria Geantă 	 * Quick & dirty translation from OP_ALG_ALGSEL_{MD5, SHA*}
5687e0880b9SHoria Geantă 	 * to OP_PCLID_DKP_{MD5, SHA*}
5697e0880b9SHoria Geantă 	 */
5707e0880b9SHoria Geantă 	protid = (adata->algtype & OP_ALG_ALGSEL_SUBMASK) |
5717e0880b9SHoria Geantă 		 (0x20 << OP_ALG_ALGSEL_SHIFT);
5727e0880b9SHoria Geantă 
5737e0880b9SHoria Geantă 	if (adata->key_inline) {
5747e0880b9SHoria Geantă 		int words;
5757e0880b9SHoria Geantă 
576e9b4913aSHoria Geantă 		if (adata->keylen > adata->keylen_pad) {
5777e0880b9SHoria Geantă 			append_operation(desc, OP_TYPE_UNI_PROTOCOL | protid |
578e9b4913aSHoria Geantă 					 OP_PCL_DKP_SRC_PTR |
579e9b4913aSHoria Geantă 					 OP_PCL_DKP_DST_IMM | adata->keylen);
580e9b4913aSHoria Geantă 			append_ptr(desc, adata->key_dma);
581e9b4913aSHoria Geantă 
582e9b4913aSHoria Geantă 			words = (ALIGN(adata->keylen_pad, CAAM_CMD_SZ) -
583e9b4913aSHoria Geantă 				 CAAM_PTR_SZ) / CAAM_CMD_SZ;
584e9b4913aSHoria Geantă 		} else {
585e9b4913aSHoria Geantă 			append_operation(desc, OP_TYPE_UNI_PROTOCOL | protid |
586e9b4913aSHoria Geantă 					 OP_PCL_DKP_SRC_IMM |
587e9b4913aSHoria Geantă 					 OP_PCL_DKP_DST_IMM | adata->keylen);
5887e0880b9SHoria Geantă 			append_data(desc, adata->key_virt, adata->keylen);
5897e0880b9SHoria Geantă 
5907e0880b9SHoria Geantă 			words = (ALIGN(adata->keylen_pad, CAAM_CMD_SZ) -
591e9b4913aSHoria Geantă 				 ALIGN(adata->keylen, CAAM_CMD_SZ)) /
592e9b4913aSHoria Geantă 				CAAM_CMD_SZ;
593e9b4913aSHoria Geantă 		}
594e9b4913aSHoria Geantă 
595e9b4913aSHoria Geantă 		/* Reserve space in descriptor buffer for the derived key */
5967e0880b9SHoria Geantă 		if (words)
5977e0880b9SHoria Geantă 			(*desc) = cpu_to_caam32(caam32_to_cpu(*desc) + words);
5987e0880b9SHoria Geantă 	} else {
5997e0880b9SHoria Geantă 		append_operation(desc, OP_TYPE_UNI_PROTOCOL | protid |
6007e0880b9SHoria Geantă 				 OP_PCL_DKP_SRC_PTR | OP_PCL_DKP_DST_PTR |
6017e0880b9SHoria Geantă 				 adata->keylen);
6027e0880b9SHoria Geantă 		append_ptr(desc, adata->key_dma);
6037e0880b9SHoria Geantă 	}
6047e0880b9SHoria Geantă }
6057e0880b9SHoria Geantă 
606cd373691SHoria Geantă #endif /* DESC_CONSTR_H */
607