1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * caam descriptor construction helper functions
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright 2008-2012 Freescale Semiconductor, Inc.
6*4882a593Smuzhiyun * Copyright 2019 NXP
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun #ifndef DESC_CONSTR_H
10*4882a593Smuzhiyun #define DESC_CONSTR_H
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include "desc.h"
13*4882a593Smuzhiyun #include "regs.h"
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun #define IMMEDIATE (1 << 23)
16*4882a593Smuzhiyun #define CAAM_CMD_SZ sizeof(u32)
17*4882a593Smuzhiyun #define CAAM_PTR_SZ caam_ptr_sz
18*4882a593Smuzhiyun #define CAAM_PTR_SZ_MAX sizeof(dma_addr_t)
19*4882a593Smuzhiyun #define CAAM_PTR_SZ_MIN sizeof(u32)
20*4882a593Smuzhiyun #define CAAM_DESC_BYTES_MAX (CAAM_CMD_SZ * MAX_CAAM_DESCSIZE)
21*4882a593Smuzhiyun #define __DESC_JOB_IO_LEN(n) (CAAM_CMD_SZ * 5 + (n) * 3)
22*4882a593Smuzhiyun #define DESC_JOB_IO_LEN __DESC_JOB_IO_LEN(CAAM_PTR_SZ)
23*4882a593Smuzhiyun #define DESC_JOB_IO_LEN_MAX __DESC_JOB_IO_LEN(CAAM_PTR_SZ_MAX)
24*4882a593Smuzhiyun #define DESC_JOB_IO_LEN_MIN __DESC_JOB_IO_LEN(CAAM_PTR_SZ_MIN)
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun /*
27*4882a593Smuzhiyun * The CAAM QI hardware constructs a job descriptor which points
28*4882a593Smuzhiyun * to shared descriptor (as pointed by context_a of FQ to CAAM).
29*4882a593Smuzhiyun * When the job descriptor is executed by deco, the whole job
30*4882a593Smuzhiyun * descriptor together with shared descriptor gets loaded in
31*4882a593Smuzhiyun * deco buffer which is 64 words long (each 32-bit).
32*4882a593Smuzhiyun *
33*4882a593Smuzhiyun * The job descriptor constructed by QI hardware has layout:
34*4882a593Smuzhiyun *
35*4882a593Smuzhiyun * HEADER (1 word)
36*4882a593Smuzhiyun * Shdesc ptr (1 or 2 words)
37*4882a593Smuzhiyun * SEQ_OUT_PTR (1 word)
38*4882a593Smuzhiyun * Out ptr (1 or 2 words)
39*4882a593Smuzhiyun * Out length (1 word)
40*4882a593Smuzhiyun * SEQ_IN_PTR (1 word)
41*4882a593Smuzhiyun * In ptr (1 or 2 words)
42*4882a593Smuzhiyun * In length (1 word)
43*4882a593Smuzhiyun *
44*4882a593Smuzhiyun * The shdesc ptr is used to fetch shared descriptor contents
45*4882a593Smuzhiyun * into deco buffer.
46*4882a593Smuzhiyun *
47*4882a593Smuzhiyun * Apart from shdesc contents, the total number of words that
48*4882a593Smuzhiyun * get loaded in deco buffer are '8' or '11'. The remaining words
49*4882a593Smuzhiyun * in deco buffer can be used for storing shared descriptor.
50*4882a593Smuzhiyun */
51*4882a593Smuzhiyun #define MAX_SDLEN ((CAAM_DESC_BYTES_MAX - DESC_JOB_IO_LEN_MIN) / CAAM_CMD_SZ)
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun #ifdef DEBUG
54*4882a593Smuzhiyun #define PRINT_POS do { printk(KERN_DEBUG "%02d: %s\n", desc_len(desc),\
55*4882a593Smuzhiyun &__func__[sizeof("append")]); } while (0)
56*4882a593Smuzhiyun #else
57*4882a593Smuzhiyun #define PRINT_POS
58*4882a593Smuzhiyun #endif
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun #define SET_OK_NO_PROP_ERRORS (IMMEDIATE | LDST_CLASS_DECO | \
61*4882a593Smuzhiyun LDST_SRCDST_WORD_DECOCTRL | \
62*4882a593Smuzhiyun (LDOFF_CHG_SHARE_OK_NO_PROP << \
63*4882a593Smuzhiyun LDST_OFFSET_SHIFT))
64*4882a593Smuzhiyun #define DISABLE_AUTO_INFO_FIFO (IMMEDIATE | LDST_CLASS_DECO | \
65*4882a593Smuzhiyun LDST_SRCDST_WORD_DECOCTRL | \
66*4882a593Smuzhiyun (LDOFF_DISABLE_AUTO_NFIFO << LDST_OFFSET_SHIFT))
67*4882a593Smuzhiyun #define ENABLE_AUTO_INFO_FIFO (IMMEDIATE | LDST_CLASS_DECO | \
68*4882a593Smuzhiyun LDST_SRCDST_WORD_DECOCTRL | \
69*4882a593Smuzhiyun (LDOFF_ENABLE_AUTO_NFIFO << LDST_OFFSET_SHIFT))
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun extern bool caam_little_end;
72*4882a593Smuzhiyun extern size_t caam_ptr_sz;
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun /*
75*4882a593Smuzhiyun * HW fetches 4 S/G table entries at a time, irrespective of how many entries
76*4882a593Smuzhiyun * are in the table. It's SW's responsibility to make sure these accesses
77*4882a593Smuzhiyun * do not have side effects.
78*4882a593Smuzhiyun */
pad_sg_nents(int sg_nents)79*4882a593Smuzhiyun static inline int pad_sg_nents(int sg_nents)
80*4882a593Smuzhiyun {
81*4882a593Smuzhiyun return ALIGN(sg_nents, 4);
82*4882a593Smuzhiyun }
83*4882a593Smuzhiyun
desc_len(u32 * const desc)84*4882a593Smuzhiyun static inline int desc_len(u32 * const desc)
85*4882a593Smuzhiyun {
86*4882a593Smuzhiyun return caam32_to_cpu(*desc) & HDR_DESCLEN_MASK;
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun
desc_bytes(void * const desc)89*4882a593Smuzhiyun static inline int desc_bytes(void * const desc)
90*4882a593Smuzhiyun {
91*4882a593Smuzhiyun return desc_len(desc) * CAAM_CMD_SZ;
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun
desc_end(u32 * const desc)94*4882a593Smuzhiyun static inline u32 *desc_end(u32 * const desc)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun return desc + desc_len(desc);
97*4882a593Smuzhiyun }
98*4882a593Smuzhiyun
sh_desc_pdb(u32 * const desc)99*4882a593Smuzhiyun static inline void *sh_desc_pdb(u32 * const desc)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun return desc + 1;
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun
init_desc(u32 * const desc,u32 options)104*4882a593Smuzhiyun static inline void init_desc(u32 * const desc, u32 options)
105*4882a593Smuzhiyun {
106*4882a593Smuzhiyun *desc = cpu_to_caam32((options | HDR_ONE) + 1);
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun
init_sh_desc(u32 * const desc,u32 options)109*4882a593Smuzhiyun static inline void init_sh_desc(u32 * const desc, u32 options)
110*4882a593Smuzhiyun {
111*4882a593Smuzhiyun PRINT_POS;
112*4882a593Smuzhiyun init_desc(desc, CMD_SHARED_DESC_HDR | options);
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun
init_sh_desc_pdb(u32 * const desc,u32 options,size_t pdb_bytes)115*4882a593Smuzhiyun static inline void init_sh_desc_pdb(u32 * const desc, u32 options,
116*4882a593Smuzhiyun size_t pdb_bytes)
117*4882a593Smuzhiyun {
118*4882a593Smuzhiyun u32 pdb_len = (pdb_bytes + CAAM_CMD_SZ - 1) / CAAM_CMD_SZ;
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun init_sh_desc(desc, (((pdb_len + 1) << HDR_START_IDX_SHIFT) + pdb_len) |
121*4882a593Smuzhiyun options);
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun
init_job_desc(u32 * const desc,u32 options)124*4882a593Smuzhiyun static inline void init_job_desc(u32 * const desc, u32 options)
125*4882a593Smuzhiyun {
126*4882a593Smuzhiyun init_desc(desc, CMD_DESC_HDR | options);
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun
init_job_desc_pdb(u32 * const desc,u32 options,size_t pdb_bytes)129*4882a593Smuzhiyun static inline void init_job_desc_pdb(u32 * const desc, u32 options,
130*4882a593Smuzhiyun size_t pdb_bytes)
131*4882a593Smuzhiyun {
132*4882a593Smuzhiyun u32 pdb_len = (pdb_bytes + CAAM_CMD_SZ - 1) / CAAM_CMD_SZ;
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun init_job_desc(desc, (((pdb_len + 1) << HDR_START_IDX_SHIFT)) | options);
135*4882a593Smuzhiyun }
136*4882a593Smuzhiyun
append_ptr(u32 * const desc,dma_addr_t ptr)137*4882a593Smuzhiyun static inline void append_ptr(u32 * const desc, dma_addr_t ptr)
138*4882a593Smuzhiyun {
139*4882a593Smuzhiyun if (caam_ptr_sz == sizeof(dma_addr_t)) {
140*4882a593Smuzhiyun dma_addr_t *offset = (dma_addr_t *)desc_end(desc);
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun *offset = cpu_to_caam_dma(ptr);
143*4882a593Smuzhiyun } else {
144*4882a593Smuzhiyun u32 *offset = (u32 *)desc_end(desc);
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun *offset = cpu_to_caam_dma(ptr);
147*4882a593Smuzhiyun }
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun (*desc) = cpu_to_caam32(caam32_to_cpu(*desc) +
150*4882a593Smuzhiyun CAAM_PTR_SZ / CAAM_CMD_SZ);
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun
init_job_desc_shared(u32 * const desc,dma_addr_t ptr,int len,u32 options)153*4882a593Smuzhiyun static inline void init_job_desc_shared(u32 * const desc, dma_addr_t ptr,
154*4882a593Smuzhiyun int len, u32 options)
155*4882a593Smuzhiyun {
156*4882a593Smuzhiyun PRINT_POS;
157*4882a593Smuzhiyun init_job_desc(desc, HDR_SHARED | options |
158*4882a593Smuzhiyun (len << HDR_START_IDX_SHIFT));
159*4882a593Smuzhiyun append_ptr(desc, ptr);
160*4882a593Smuzhiyun }
161*4882a593Smuzhiyun
append_data(u32 * const desc,const void * data,int len)162*4882a593Smuzhiyun static inline void append_data(u32 * const desc, const void *data, int len)
163*4882a593Smuzhiyun {
164*4882a593Smuzhiyun u32 *offset = desc_end(desc);
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun if (len) /* avoid sparse warning: memcpy with byte count of 0 */
167*4882a593Smuzhiyun memcpy(offset, data, len);
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun (*desc) = cpu_to_caam32(caam32_to_cpu(*desc) +
170*4882a593Smuzhiyun (len + CAAM_CMD_SZ - 1) / CAAM_CMD_SZ);
171*4882a593Smuzhiyun }
172*4882a593Smuzhiyun
append_cmd(u32 * const desc,u32 command)173*4882a593Smuzhiyun static inline void append_cmd(u32 * const desc, u32 command)
174*4882a593Smuzhiyun {
175*4882a593Smuzhiyun u32 *cmd = desc_end(desc);
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun *cmd = cpu_to_caam32(command);
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun (*desc) = cpu_to_caam32(caam32_to_cpu(*desc) + 1);
180*4882a593Smuzhiyun }
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun #define append_u32 append_cmd
183*4882a593Smuzhiyun
append_u64(u32 * const desc,u64 data)184*4882a593Smuzhiyun static inline void append_u64(u32 * const desc, u64 data)
185*4882a593Smuzhiyun {
186*4882a593Smuzhiyun u32 *offset = desc_end(desc);
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun /* Only 32-bit alignment is guaranteed in descriptor buffer */
189*4882a593Smuzhiyun if (caam_little_end) {
190*4882a593Smuzhiyun *offset = cpu_to_caam32(lower_32_bits(data));
191*4882a593Smuzhiyun *(++offset) = cpu_to_caam32(upper_32_bits(data));
192*4882a593Smuzhiyun } else {
193*4882a593Smuzhiyun *offset = cpu_to_caam32(upper_32_bits(data));
194*4882a593Smuzhiyun *(++offset) = cpu_to_caam32(lower_32_bits(data));
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun (*desc) = cpu_to_caam32(caam32_to_cpu(*desc) + 2);
198*4882a593Smuzhiyun }
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun /* Write command without affecting header, and return pointer to next word */
write_cmd(u32 * const desc,u32 command)201*4882a593Smuzhiyun static inline u32 *write_cmd(u32 * const desc, u32 command)
202*4882a593Smuzhiyun {
203*4882a593Smuzhiyun *desc = cpu_to_caam32(command);
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun return desc + 1;
206*4882a593Smuzhiyun }
207*4882a593Smuzhiyun
append_cmd_ptr(u32 * const desc,dma_addr_t ptr,int len,u32 command)208*4882a593Smuzhiyun static inline void append_cmd_ptr(u32 * const desc, dma_addr_t ptr, int len,
209*4882a593Smuzhiyun u32 command)
210*4882a593Smuzhiyun {
211*4882a593Smuzhiyun append_cmd(desc, command | len);
212*4882a593Smuzhiyun append_ptr(desc, ptr);
213*4882a593Smuzhiyun }
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun /* Write length after pointer, rather than inside command */
append_cmd_ptr_extlen(u32 * const desc,dma_addr_t ptr,unsigned int len,u32 command)216*4882a593Smuzhiyun static inline void append_cmd_ptr_extlen(u32 * const desc, dma_addr_t ptr,
217*4882a593Smuzhiyun unsigned int len, u32 command)
218*4882a593Smuzhiyun {
219*4882a593Smuzhiyun append_cmd(desc, command);
220*4882a593Smuzhiyun if (!(command & (SQIN_RTO | SQIN_PRE)))
221*4882a593Smuzhiyun append_ptr(desc, ptr);
222*4882a593Smuzhiyun append_cmd(desc, len);
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun
append_cmd_data(u32 * const desc,const void * data,int len,u32 command)225*4882a593Smuzhiyun static inline void append_cmd_data(u32 * const desc, const void *data, int len,
226*4882a593Smuzhiyun u32 command)
227*4882a593Smuzhiyun {
228*4882a593Smuzhiyun append_cmd(desc, command | IMMEDIATE | len);
229*4882a593Smuzhiyun append_data(desc, data, len);
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun #define APPEND_CMD_RET(cmd, op) \
233*4882a593Smuzhiyun static inline u32 *append_##cmd(u32 * const desc, u32 options) \
234*4882a593Smuzhiyun { \
235*4882a593Smuzhiyun u32 *cmd = desc_end(desc); \
236*4882a593Smuzhiyun PRINT_POS; \
237*4882a593Smuzhiyun append_cmd(desc, CMD_##op | options); \
238*4882a593Smuzhiyun return cmd; \
239*4882a593Smuzhiyun }
APPEND_CMD_RET(jump,JUMP)240*4882a593Smuzhiyun APPEND_CMD_RET(jump, JUMP)
241*4882a593Smuzhiyun APPEND_CMD_RET(move, MOVE)
242*4882a593Smuzhiyun APPEND_CMD_RET(move_len, MOVE_LEN)
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun static inline void set_jump_tgt_here(u32 * const desc, u32 *jump_cmd)
245*4882a593Smuzhiyun {
246*4882a593Smuzhiyun *jump_cmd = cpu_to_caam32(caam32_to_cpu(*jump_cmd) |
247*4882a593Smuzhiyun (desc_len(desc) - (jump_cmd - desc)));
248*4882a593Smuzhiyun }
249*4882a593Smuzhiyun
set_move_tgt_here(u32 * const desc,u32 * move_cmd)250*4882a593Smuzhiyun static inline void set_move_tgt_here(u32 * const desc, u32 *move_cmd)
251*4882a593Smuzhiyun {
252*4882a593Smuzhiyun u32 val = caam32_to_cpu(*move_cmd);
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun val &= ~MOVE_OFFSET_MASK;
255*4882a593Smuzhiyun val |= (desc_len(desc) << (MOVE_OFFSET_SHIFT + 2)) & MOVE_OFFSET_MASK;
256*4882a593Smuzhiyun *move_cmd = cpu_to_caam32(val);
257*4882a593Smuzhiyun }
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun #define APPEND_CMD(cmd, op) \
260*4882a593Smuzhiyun static inline void append_##cmd(u32 * const desc, u32 options) \
261*4882a593Smuzhiyun { \
262*4882a593Smuzhiyun PRINT_POS; \
263*4882a593Smuzhiyun append_cmd(desc, CMD_##op | options); \
264*4882a593Smuzhiyun }
APPEND_CMD(operation,OPERATION)265*4882a593Smuzhiyun APPEND_CMD(operation, OPERATION)
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun #define APPEND_CMD_LEN(cmd, op) \
268*4882a593Smuzhiyun static inline void append_##cmd(u32 * const desc, unsigned int len, \
269*4882a593Smuzhiyun u32 options) \
270*4882a593Smuzhiyun { \
271*4882a593Smuzhiyun PRINT_POS; \
272*4882a593Smuzhiyun append_cmd(desc, CMD_##op | len | options); \
273*4882a593Smuzhiyun }
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun APPEND_CMD_LEN(seq_load, SEQ_LOAD)
276*4882a593Smuzhiyun APPEND_CMD_LEN(seq_store, SEQ_STORE)
277*4882a593Smuzhiyun APPEND_CMD_LEN(seq_fifo_load, SEQ_FIFO_LOAD)
278*4882a593Smuzhiyun APPEND_CMD_LEN(seq_fifo_store, SEQ_FIFO_STORE)
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun #define APPEND_CMD_PTR(cmd, op) \
281*4882a593Smuzhiyun static inline void append_##cmd(u32 * const desc, dma_addr_t ptr, \
282*4882a593Smuzhiyun unsigned int len, u32 options) \
283*4882a593Smuzhiyun { \
284*4882a593Smuzhiyun PRINT_POS; \
285*4882a593Smuzhiyun append_cmd_ptr(desc, ptr, len, CMD_##op | options); \
286*4882a593Smuzhiyun }
287*4882a593Smuzhiyun APPEND_CMD_PTR(key, KEY)
288*4882a593Smuzhiyun APPEND_CMD_PTR(load, LOAD)
289*4882a593Smuzhiyun APPEND_CMD_PTR(fifo_load, FIFO_LOAD)
290*4882a593Smuzhiyun APPEND_CMD_PTR(fifo_store, FIFO_STORE)
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun static inline void append_store(u32 * const desc, dma_addr_t ptr,
293*4882a593Smuzhiyun unsigned int len, u32 options)
294*4882a593Smuzhiyun {
295*4882a593Smuzhiyun u32 cmd_src;
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun cmd_src = options & LDST_SRCDST_MASK;
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun append_cmd(desc, CMD_STORE | options | len);
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun /* The following options do not require pointer */
302*4882a593Smuzhiyun if (!(cmd_src == LDST_SRCDST_WORD_DESCBUF_SHARED ||
303*4882a593Smuzhiyun cmd_src == LDST_SRCDST_WORD_DESCBUF_JOB ||
304*4882a593Smuzhiyun cmd_src == LDST_SRCDST_WORD_DESCBUF_JOB_WE ||
305*4882a593Smuzhiyun cmd_src == LDST_SRCDST_WORD_DESCBUF_SHARED_WE))
306*4882a593Smuzhiyun append_ptr(desc, ptr);
307*4882a593Smuzhiyun }
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun #define APPEND_SEQ_PTR_INTLEN(cmd, op) \
310*4882a593Smuzhiyun static inline void append_seq_##cmd##_ptr_intlen(u32 * const desc, \
311*4882a593Smuzhiyun dma_addr_t ptr, \
312*4882a593Smuzhiyun unsigned int len, \
313*4882a593Smuzhiyun u32 options) \
314*4882a593Smuzhiyun { \
315*4882a593Smuzhiyun PRINT_POS; \
316*4882a593Smuzhiyun if (options & (SQIN_RTO | SQIN_PRE)) \
317*4882a593Smuzhiyun append_cmd(desc, CMD_SEQ_##op##_PTR | len | options); \
318*4882a593Smuzhiyun else \
319*4882a593Smuzhiyun append_cmd_ptr(desc, ptr, len, CMD_SEQ_##op##_PTR | options); \
320*4882a593Smuzhiyun }
321*4882a593Smuzhiyun APPEND_SEQ_PTR_INTLEN(in, IN)
322*4882a593Smuzhiyun APPEND_SEQ_PTR_INTLEN(out, OUT)
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun #define APPEND_CMD_PTR_TO_IMM(cmd, op) \
325*4882a593Smuzhiyun static inline void append_##cmd##_as_imm(u32 * const desc, const void *data, \
326*4882a593Smuzhiyun unsigned int len, u32 options) \
327*4882a593Smuzhiyun { \
328*4882a593Smuzhiyun PRINT_POS; \
329*4882a593Smuzhiyun append_cmd_data(desc, data, len, CMD_##op | options); \
330*4882a593Smuzhiyun }
331*4882a593Smuzhiyun APPEND_CMD_PTR_TO_IMM(load, LOAD);
332*4882a593Smuzhiyun APPEND_CMD_PTR_TO_IMM(fifo_load, FIFO_LOAD);
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun #define APPEND_CMD_PTR_EXTLEN(cmd, op) \
335*4882a593Smuzhiyun static inline void append_##cmd##_extlen(u32 * const desc, dma_addr_t ptr, \
336*4882a593Smuzhiyun unsigned int len, u32 options) \
337*4882a593Smuzhiyun { \
338*4882a593Smuzhiyun PRINT_POS; \
339*4882a593Smuzhiyun append_cmd_ptr_extlen(desc, ptr, len, CMD_##op | SQIN_EXT | options); \
340*4882a593Smuzhiyun }
341*4882a593Smuzhiyun APPEND_CMD_PTR_EXTLEN(seq_in_ptr, SEQ_IN_PTR)
342*4882a593Smuzhiyun APPEND_CMD_PTR_EXTLEN(seq_out_ptr, SEQ_OUT_PTR)
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun /*
345*4882a593Smuzhiyun * Determine whether to store length internally or externally depending on
346*4882a593Smuzhiyun * the size of its type
347*4882a593Smuzhiyun */
348*4882a593Smuzhiyun #define APPEND_CMD_PTR_LEN(cmd, op, type) \
349*4882a593Smuzhiyun static inline void append_##cmd(u32 * const desc, dma_addr_t ptr, \
350*4882a593Smuzhiyun type len, u32 options) \
351*4882a593Smuzhiyun { \
352*4882a593Smuzhiyun PRINT_POS; \
353*4882a593Smuzhiyun if (sizeof(type) > sizeof(u16)) \
354*4882a593Smuzhiyun append_##cmd##_extlen(desc, ptr, len, options); \
355*4882a593Smuzhiyun else \
356*4882a593Smuzhiyun append_##cmd##_intlen(desc, ptr, len, options); \
357*4882a593Smuzhiyun }
358*4882a593Smuzhiyun APPEND_CMD_PTR_LEN(seq_in_ptr, SEQ_IN_PTR, u32)
359*4882a593Smuzhiyun APPEND_CMD_PTR_LEN(seq_out_ptr, SEQ_OUT_PTR, u32)
360*4882a593Smuzhiyun
361*4882a593Smuzhiyun /*
362*4882a593Smuzhiyun * 2nd variant for commands whose specified immediate length differs
363*4882a593Smuzhiyun * from length of immediate data provided, e.g., split keys
364*4882a593Smuzhiyun */
365*4882a593Smuzhiyun #define APPEND_CMD_PTR_TO_IMM2(cmd, op) \
366*4882a593Smuzhiyun static inline void append_##cmd##_as_imm(u32 * const desc, const void *data, \
367*4882a593Smuzhiyun unsigned int data_len, \
368*4882a593Smuzhiyun unsigned int len, u32 options) \
369*4882a593Smuzhiyun { \
370*4882a593Smuzhiyun PRINT_POS; \
371*4882a593Smuzhiyun append_cmd(desc, CMD_##op | IMMEDIATE | len | options); \
372*4882a593Smuzhiyun append_data(desc, data, data_len); \
373*4882a593Smuzhiyun }
374*4882a593Smuzhiyun APPEND_CMD_PTR_TO_IMM2(key, KEY);
375*4882a593Smuzhiyun
376*4882a593Smuzhiyun #define APPEND_CMD_RAW_IMM(cmd, op, type) \
377*4882a593Smuzhiyun static inline void append_##cmd##_imm_##type(u32 * const desc, type immediate, \
378*4882a593Smuzhiyun u32 options) \
379*4882a593Smuzhiyun { \
380*4882a593Smuzhiyun PRINT_POS; \
381*4882a593Smuzhiyun if (options & LDST_LEN_MASK) \
382*4882a593Smuzhiyun append_cmd(desc, CMD_##op | IMMEDIATE | options); \
383*4882a593Smuzhiyun else \
384*4882a593Smuzhiyun append_cmd(desc, CMD_##op | IMMEDIATE | options | \
385*4882a593Smuzhiyun sizeof(type)); \
386*4882a593Smuzhiyun append_cmd(desc, immediate); \
387*4882a593Smuzhiyun }
388*4882a593Smuzhiyun APPEND_CMD_RAW_IMM(load, LOAD, u32);
389*4882a593Smuzhiyun
390*4882a593Smuzhiyun /*
391*4882a593Smuzhiyun * ee - endianness
392*4882a593Smuzhiyun * size - size of immediate type in bytes
393*4882a593Smuzhiyun */
394*4882a593Smuzhiyun #define APPEND_CMD_RAW_IMM2(cmd, op, ee, size) \
395*4882a593Smuzhiyun static inline void append_##cmd##_imm_##ee##size(u32 *desc, \
396*4882a593Smuzhiyun u##size immediate, \
397*4882a593Smuzhiyun u32 options) \
398*4882a593Smuzhiyun { \
399*4882a593Smuzhiyun __##ee##size data = cpu_to_##ee##size(immediate); \
400*4882a593Smuzhiyun PRINT_POS; \
401*4882a593Smuzhiyun append_cmd(desc, CMD_##op | IMMEDIATE | options | sizeof(data)); \
402*4882a593Smuzhiyun append_data(desc, &data, sizeof(data)); \
403*4882a593Smuzhiyun }
404*4882a593Smuzhiyun
405*4882a593Smuzhiyun APPEND_CMD_RAW_IMM2(load, LOAD, be, 32);
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun /*
408*4882a593Smuzhiyun * Append math command. Only the last part of destination and source need to
409*4882a593Smuzhiyun * be specified
410*4882a593Smuzhiyun */
411*4882a593Smuzhiyun #define APPEND_MATH(op, desc, dest, src_0, src_1, len) \
412*4882a593Smuzhiyun append_cmd(desc, CMD_MATH | MATH_FUN_##op | MATH_DEST_##dest | \
413*4882a593Smuzhiyun MATH_SRC0_##src_0 | MATH_SRC1_##src_1 | (u32)len);
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun #define append_math_add(desc, dest, src0, src1, len) \
416*4882a593Smuzhiyun APPEND_MATH(ADD, desc, dest, src0, src1, len)
417*4882a593Smuzhiyun #define append_math_sub(desc, dest, src0, src1, len) \
418*4882a593Smuzhiyun APPEND_MATH(SUB, desc, dest, src0, src1, len)
419*4882a593Smuzhiyun #define append_math_add_c(desc, dest, src0, src1, len) \
420*4882a593Smuzhiyun APPEND_MATH(ADDC, desc, dest, src0, src1, len)
421*4882a593Smuzhiyun #define append_math_sub_b(desc, dest, src0, src1, len) \
422*4882a593Smuzhiyun APPEND_MATH(SUBB, desc, dest, src0, src1, len)
423*4882a593Smuzhiyun #define append_math_and(desc, dest, src0, src1, len) \
424*4882a593Smuzhiyun APPEND_MATH(AND, desc, dest, src0, src1, len)
425*4882a593Smuzhiyun #define append_math_or(desc, dest, src0, src1, len) \
426*4882a593Smuzhiyun APPEND_MATH(OR, desc, dest, src0, src1, len)
427*4882a593Smuzhiyun #define append_math_xor(desc, dest, src0, src1, len) \
428*4882a593Smuzhiyun APPEND_MATH(XOR, desc, dest, src0, src1, len)
429*4882a593Smuzhiyun #define append_math_lshift(desc, dest, src0, src1, len) \
430*4882a593Smuzhiyun APPEND_MATH(LSHIFT, desc, dest, src0, src1, len)
431*4882a593Smuzhiyun #define append_math_rshift(desc, dest, src0, src1, len) \
432*4882a593Smuzhiyun APPEND_MATH(RSHIFT, desc, dest, src0, src1, len)
433*4882a593Smuzhiyun #define append_math_ldshift(desc, dest, src0, src1, len) \
434*4882a593Smuzhiyun APPEND_MATH(SHLD, desc, dest, src0, src1, len)
435*4882a593Smuzhiyun
436*4882a593Smuzhiyun /* Exactly one source is IMM. Data is passed in as u32 value */
437*4882a593Smuzhiyun #define APPEND_MATH_IMM_u32(op, desc, dest, src_0, src_1, data) \
438*4882a593Smuzhiyun do { \
439*4882a593Smuzhiyun APPEND_MATH(op, desc, dest, src_0, src_1, CAAM_CMD_SZ); \
440*4882a593Smuzhiyun append_cmd(desc, data); \
441*4882a593Smuzhiyun } while (0)
442*4882a593Smuzhiyun
443*4882a593Smuzhiyun #define append_math_add_imm_u32(desc, dest, src0, src1, data) \
444*4882a593Smuzhiyun APPEND_MATH_IMM_u32(ADD, desc, dest, src0, src1, data)
445*4882a593Smuzhiyun #define append_math_sub_imm_u32(desc, dest, src0, src1, data) \
446*4882a593Smuzhiyun APPEND_MATH_IMM_u32(SUB, desc, dest, src0, src1, data)
447*4882a593Smuzhiyun #define append_math_add_c_imm_u32(desc, dest, src0, src1, data) \
448*4882a593Smuzhiyun APPEND_MATH_IMM_u32(ADDC, desc, dest, src0, src1, data)
449*4882a593Smuzhiyun #define append_math_sub_b_imm_u32(desc, dest, src0, src1, data) \
450*4882a593Smuzhiyun APPEND_MATH_IMM_u32(SUBB, desc, dest, src0, src1, data)
451*4882a593Smuzhiyun #define append_math_and_imm_u32(desc, dest, src0, src1, data) \
452*4882a593Smuzhiyun APPEND_MATH_IMM_u32(AND, desc, dest, src0, src1, data)
453*4882a593Smuzhiyun #define append_math_or_imm_u32(desc, dest, src0, src1, data) \
454*4882a593Smuzhiyun APPEND_MATH_IMM_u32(OR, desc, dest, src0, src1, data)
455*4882a593Smuzhiyun #define append_math_xor_imm_u32(desc, dest, src0, src1, data) \
456*4882a593Smuzhiyun APPEND_MATH_IMM_u32(XOR, desc, dest, src0, src1, data)
457*4882a593Smuzhiyun #define append_math_lshift_imm_u32(desc, dest, src0, src1, data) \
458*4882a593Smuzhiyun APPEND_MATH_IMM_u32(LSHIFT, desc, dest, src0, src1, data)
459*4882a593Smuzhiyun #define append_math_rshift_imm_u32(desc, dest, src0, src1, data) \
460*4882a593Smuzhiyun APPEND_MATH_IMM_u32(RSHIFT, desc, dest, src0, src1, data)
461*4882a593Smuzhiyun
462*4882a593Smuzhiyun /* Exactly one source is IMM. Data is passed in as u64 value */
463*4882a593Smuzhiyun #define APPEND_MATH_IMM_u64(op, desc, dest, src_0, src_1, data) \
464*4882a593Smuzhiyun do { \
465*4882a593Smuzhiyun u32 upper = (data >> 16) >> 16; \
466*4882a593Smuzhiyun APPEND_MATH(op, desc, dest, src_0, src_1, CAAM_CMD_SZ * 2 | \
467*4882a593Smuzhiyun (upper ? 0 : MATH_IFB)); \
468*4882a593Smuzhiyun if (upper) \
469*4882a593Smuzhiyun append_u64(desc, data); \
470*4882a593Smuzhiyun else \
471*4882a593Smuzhiyun append_u32(desc, lower_32_bits(data)); \
472*4882a593Smuzhiyun } while (0)
473*4882a593Smuzhiyun
474*4882a593Smuzhiyun #define append_math_add_imm_u64(desc, dest, src0, src1, data) \
475*4882a593Smuzhiyun APPEND_MATH_IMM_u64(ADD, desc, dest, src0, src1, data)
476*4882a593Smuzhiyun #define append_math_sub_imm_u64(desc, dest, src0, src1, data) \
477*4882a593Smuzhiyun APPEND_MATH_IMM_u64(SUB, desc, dest, src0, src1, data)
478*4882a593Smuzhiyun #define append_math_add_c_imm_u64(desc, dest, src0, src1, data) \
479*4882a593Smuzhiyun APPEND_MATH_IMM_u64(ADDC, desc, dest, src0, src1, data)
480*4882a593Smuzhiyun #define append_math_sub_b_imm_u64(desc, dest, src0, src1, data) \
481*4882a593Smuzhiyun APPEND_MATH_IMM_u64(SUBB, desc, dest, src0, src1, data)
482*4882a593Smuzhiyun #define append_math_and_imm_u64(desc, dest, src0, src1, data) \
483*4882a593Smuzhiyun APPEND_MATH_IMM_u64(AND, desc, dest, src0, src1, data)
484*4882a593Smuzhiyun #define append_math_or_imm_u64(desc, dest, src0, src1, data) \
485*4882a593Smuzhiyun APPEND_MATH_IMM_u64(OR, desc, dest, src0, src1, data)
486*4882a593Smuzhiyun #define append_math_xor_imm_u64(desc, dest, src0, src1, data) \
487*4882a593Smuzhiyun APPEND_MATH_IMM_u64(XOR, desc, dest, src0, src1, data)
488*4882a593Smuzhiyun #define append_math_lshift_imm_u64(desc, dest, src0, src1, data) \
489*4882a593Smuzhiyun APPEND_MATH_IMM_u64(LSHIFT, desc, dest, src0, src1, data)
490*4882a593Smuzhiyun #define append_math_rshift_imm_u64(desc, dest, src0, src1, data) \
491*4882a593Smuzhiyun APPEND_MATH_IMM_u64(RSHIFT, desc, dest, src0, src1, data)
492*4882a593Smuzhiyun
493*4882a593Smuzhiyun /**
494*4882a593Smuzhiyun * struct alginfo - Container for algorithm details
495*4882a593Smuzhiyun * @algtype: algorithm selector; for valid values, see documentation of the
496*4882a593Smuzhiyun * functions where it is used.
497*4882a593Smuzhiyun * @keylen: length of the provided algorithm key, in bytes
498*4882a593Smuzhiyun * @keylen_pad: padded length of the provided algorithm key, in bytes
499*4882a593Smuzhiyun * @key_dma: dma (bus) address where algorithm key resides
500*4882a593Smuzhiyun * @key_virt: virtual address where algorithm key resides
501*4882a593Smuzhiyun * @key_inline: true - key can be inlined in the descriptor; false - key is
502*4882a593Smuzhiyun * referenced by the descriptor
503*4882a593Smuzhiyun */
504*4882a593Smuzhiyun struct alginfo {
505*4882a593Smuzhiyun u32 algtype;
506*4882a593Smuzhiyun unsigned int keylen;
507*4882a593Smuzhiyun unsigned int keylen_pad;
508*4882a593Smuzhiyun dma_addr_t key_dma;
509*4882a593Smuzhiyun const void *key_virt;
510*4882a593Smuzhiyun bool key_inline;
511*4882a593Smuzhiyun };
512*4882a593Smuzhiyun
513*4882a593Smuzhiyun /**
514*4882a593Smuzhiyun * desc_inline_query() - Provide indications on which data items can be inlined
515*4882a593Smuzhiyun * and which shall be referenced in a shared descriptor.
516*4882a593Smuzhiyun * @sd_base_len: Shared descriptor base length - bytes consumed by the commands,
517*4882a593Smuzhiyun * excluding the data items to be inlined (or corresponding
518*4882a593Smuzhiyun * pointer if an item is not inlined). Each cnstr_* function that
519*4882a593Smuzhiyun * generates descriptors should have a define mentioning
520*4882a593Smuzhiyun * corresponding length.
521*4882a593Smuzhiyun * @jd_len: Maximum length of the job descriptor(s) that will be used
522*4882a593Smuzhiyun * together with the shared descriptor.
523*4882a593Smuzhiyun * @data_len: Array of lengths of the data items trying to be inlined
524*4882a593Smuzhiyun * @inl_mask: 32bit mask with bit x = 1 if data item x can be inlined, 0
525*4882a593Smuzhiyun * otherwise.
526*4882a593Smuzhiyun * @count: Number of data items (size of @data_len array); must be <= 32
527*4882a593Smuzhiyun *
528*4882a593Smuzhiyun * Return: 0 if data can be inlined / referenced, negative value if not. If 0,
529*4882a593Smuzhiyun * check @inl_mask for details.
530*4882a593Smuzhiyun */
desc_inline_query(unsigned int sd_base_len,unsigned int jd_len,unsigned int * data_len,u32 * inl_mask,unsigned int count)531*4882a593Smuzhiyun static inline int desc_inline_query(unsigned int sd_base_len,
532*4882a593Smuzhiyun unsigned int jd_len, unsigned int *data_len,
533*4882a593Smuzhiyun u32 *inl_mask, unsigned int count)
534*4882a593Smuzhiyun {
535*4882a593Smuzhiyun int rem_bytes = (int)(CAAM_DESC_BYTES_MAX - sd_base_len - jd_len);
536*4882a593Smuzhiyun unsigned int i;
537*4882a593Smuzhiyun
538*4882a593Smuzhiyun *inl_mask = 0;
539*4882a593Smuzhiyun for (i = 0; (i < count) && (rem_bytes > 0); i++) {
540*4882a593Smuzhiyun if (rem_bytes - (int)(data_len[i] +
541*4882a593Smuzhiyun (count - i - 1) * CAAM_PTR_SZ) >= 0) {
542*4882a593Smuzhiyun rem_bytes -= data_len[i];
543*4882a593Smuzhiyun *inl_mask |= (1 << i);
544*4882a593Smuzhiyun } else {
545*4882a593Smuzhiyun rem_bytes -= CAAM_PTR_SZ;
546*4882a593Smuzhiyun }
547*4882a593Smuzhiyun }
548*4882a593Smuzhiyun
549*4882a593Smuzhiyun return (rem_bytes >= 0) ? 0 : -1;
550*4882a593Smuzhiyun }
551*4882a593Smuzhiyun
552*4882a593Smuzhiyun /**
553*4882a593Smuzhiyun * append_proto_dkp - Derived Key Protocol (DKP): key -> split key
554*4882a593Smuzhiyun * @desc: pointer to buffer used for descriptor construction
555*4882a593Smuzhiyun * @adata: pointer to authentication transform definitions.
556*4882a593Smuzhiyun * keylen should be the length of initial key, while keylen_pad
557*4882a593Smuzhiyun * the length of the derived (split) key.
558*4882a593Smuzhiyun * Valid algorithm values - one of OP_ALG_ALGSEL_{MD5, SHA1, SHA224,
559*4882a593Smuzhiyun * SHA256, SHA384, SHA512}.
560*4882a593Smuzhiyun */
append_proto_dkp(u32 * const desc,struct alginfo * adata)561*4882a593Smuzhiyun static inline void append_proto_dkp(u32 * const desc, struct alginfo *adata)
562*4882a593Smuzhiyun {
563*4882a593Smuzhiyun u32 protid;
564*4882a593Smuzhiyun
565*4882a593Smuzhiyun /*
566*4882a593Smuzhiyun * Quick & dirty translation from OP_ALG_ALGSEL_{MD5, SHA*}
567*4882a593Smuzhiyun * to OP_PCLID_DKP_{MD5, SHA*}
568*4882a593Smuzhiyun */
569*4882a593Smuzhiyun protid = (adata->algtype & OP_ALG_ALGSEL_SUBMASK) |
570*4882a593Smuzhiyun (0x20 << OP_ALG_ALGSEL_SHIFT);
571*4882a593Smuzhiyun
572*4882a593Smuzhiyun if (adata->key_inline) {
573*4882a593Smuzhiyun int words;
574*4882a593Smuzhiyun
575*4882a593Smuzhiyun if (adata->keylen > adata->keylen_pad) {
576*4882a593Smuzhiyun append_operation(desc, OP_TYPE_UNI_PROTOCOL | protid |
577*4882a593Smuzhiyun OP_PCL_DKP_SRC_PTR |
578*4882a593Smuzhiyun OP_PCL_DKP_DST_IMM | adata->keylen);
579*4882a593Smuzhiyun append_ptr(desc, adata->key_dma);
580*4882a593Smuzhiyun
581*4882a593Smuzhiyun words = (ALIGN(adata->keylen_pad, CAAM_CMD_SZ) -
582*4882a593Smuzhiyun CAAM_PTR_SZ) / CAAM_CMD_SZ;
583*4882a593Smuzhiyun } else {
584*4882a593Smuzhiyun append_operation(desc, OP_TYPE_UNI_PROTOCOL | protid |
585*4882a593Smuzhiyun OP_PCL_DKP_SRC_IMM |
586*4882a593Smuzhiyun OP_PCL_DKP_DST_IMM | adata->keylen);
587*4882a593Smuzhiyun append_data(desc, adata->key_virt, adata->keylen);
588*4882a593Smuzhiyun
589*4882a593Smuzhiyun words = (ALIGN(adata->keylen_pad, CAAM_CMD_SZ) -
590*4882a593Smuzhiyun ALIGN(adata->keylen, CAAM_CMD_SZ)) /
591*4882a593Smuzhiyun CAAM_CMD_SZ;
592*4882a593Smuzhiyun }
593*4882a593Smuzhiyun
594*4882a593Smuzhiyun /* Reserve space in descriptor buffer for the derived key */
595*4882a593Smuzhiyun if (words)
596*4882a593Smuzhiyun (*desc) = cpu_to_caam32(caam32_to_cpu(*desc) + words);
597*4882a593Smuzhiyun } else {
598*4882a593Smuzhiyun append_operation(desc, OP_TYPE_UNI_PROTOCOL | protid |
599*4882a593Smuzhiyun OP_PCL_DKP_SRC_PTR | OP_PCL_DKP_DST_PTR |
600*4882a593Smuzhiyun adata->keylen);
601*4882a593Smuzhiyun append_ptr(desc, adata->key_dma);
602*4882a593Smuzhiyun }
603*4882a593Smuzhiyun }
604*4882a593Smuzhiyun
605*4882a593Smuzhiyun #endif /* DESC_CONSTR_H */
606