xref: /dpdk/drivers/common/dpaax/caamflib/rta/move_cmd.h (revision 68a03efeed657e6e05f281479b33b51102797e15)
1 /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
2  *
3  * Copyright 2008-2016 Freescale Semiconductor Inc.
4  * Copyright 2016,2019 NXP
5  */
6 
7 #ifndef __RTA_MOVE_CMD_H__
8 #define __RTA_MOVE_CMD_H__
9 
10 #define MOVE_SET_AUX_SRC	0x01
11 #define MOVE_SET_AUX_DST	0x02
12 #define MOVE_SET_AUX_LS		0x03
13 #define MOVE_SET_LEN_16b	0x04
14 
15 #define MOVE_SET_AUX_MATH	0x10
16 #define MOVE_SET_AUX_MATH_SRC	(MOVE_SET_AUX_SRC | MOVE_SET_AUX_MATH)
17 #define MOVE_SET_AUX_MATH_DST	(MOVE_SET_AUX_DST | MOVE_SET_AUX_MATH)
18 
19 #define MASK_16b  0xFF
20 
21 /* MOVE command type */
22 #define __MOVE		1
23 #define __MOVEB		2
24 #define __MOVEDW	3
25 
26 extern enum rta_sec_era rta_sec_era;
27 
28 static const uint32_t move_src_table[][2] = {
29 /*1*/	{ CONTEXT1, MOVE_SRC_CLASS1CTX },
30 	{ CONTEXT2, MOVE_SRC_CLASS2CTX },
31 	{ OFIFO,    MOVE_SRC_OUTFIFO },
32 	{ DESCBUF,  MOVE_SRC_DESCBUF },
33 	{ MATH0,    MOVE_SRC_MATH0 },
34 	{ MATH1,    MOVE_SRC_MATH1 },
35 	{ MATH2,    MOVE_SRC_MATH2 },
36 	{ MATH3,    MOVE_SRC_MATH3 },
37 /*9*/	{ IFIFOABD, MOVE_SRC_INFIFO },
38 	{ IFIFOAB1, MOVE_SRC_INFIFO_CL | MOVE_AUX_LS },
39 	{ IFIFOAB2, MOVE_SRC_INFIFO_CL },
40 /*12*/	{ ABD,      MOVE_SRC_INFIFO_NO_NFIFO },
41 	{ AB1,      MOVE_SRC_INFIFO_NO_NFIFO | MOVE_AUX_LS },
42 	{ AB2,      MOVE_SRC_INFIFO_NO_NFIFO | MOVE_AUX_MS }
43 };
44 
45 /* Allowed MOVE / MOVE_LEN sources for each SEC Era.
46  * Values represent the number of entries from move_src_table[] that are
47  * supported.
48  */
49 static const unsigned int move_src_table_sz[] = {9, 11, 14, 14, 14, 14, 14, 14,
50 						 14, 14};
51 
52 static const uint32_t move_dst_table[][2] = {
53 /*1*/	{ CONTEXT1,  MOVE_DEST_CLASS1CTX },
54 	{ CONTEXT2,  MOVE_DEST_CLASS2CTX },
55 	{ OFIFO,     MOVE_DEST_OUTFIFO },
56 	{ DESCBUF,   MOVE_DEST_DESCBUF },
57 	{ MATH0,     MOVE_DEST_MATH0 },
58 	{ MATH1,     MOVE_DEST_MATH1 },
59 	{ MATH2,     MOVE_DEST_MATH2 },
60 	{ MATH3,     MOVE_DEST_MATH3 },
61 	{ IFIFOAB1,  MOVE_DEST_CLASS1INFIFO },
62 	{ IFIFOAB2,  MOVE_DEST_CLASS2INFIFO },
63 	{ PKA,       MOVE_DEST_PK_A },
64 	{ KEY1,      MOVE_DEST_CLASS1KEY },
65 	{ KEY2,      MOVE_DEST_CLASS2KEY },
66 /*14*/	{ IFIFO,     MOVE_DEST_INFIFO },
67 /*15*/	{ ALTSOURCE,  MOVE_DEST_ALTSOURCE}
68 };
69 
70 /* Allowed MOVE / MOVE_LEN destinations for each SEC Era.
71  * Values represent the number of entries from move_dst_table[] that are
72  * supported.
73  */
74 static const
75 unsigned int move_dst_table_sz[] = {13, 14, 14, 15, 15, 15, 15, 15, 15, 15};
76 
77 static inline int
78 set_move_offset(struct program *program __maybe_unused,
79 		uint64_t src, uint16_t src_offset,
80 		uint64_t dst, uint16_t dst_offset,
81 		uint16_t *offset, uint16_t *opt);
82 
83 static inline int
84 math_offset(uint16_t offset);
85 
86 static inline int
87 rta_move(struct program *program, int cmd_type, uint64_t src,
88 	 uint16_t src_offset, uint64_t dst,
89 	 uint16_t dst_offset, uint32_t length, uint32_t flags)
90 {
91 	uint32_t opcode = 0;
92 	uint16_t offset = 0, opt = 0;
93 	uint32_t val = 0;
94 	int ret = -EINVAL;
95 	bool is_move_len_cmd = false;
96 	unsigned int start_pc = program->current_pc;
97 
98 	if ((rta_sec_era < RTA_SEC_ERA_7) && (cmd_type != __MOVE)) {
99 		pr_err("MOVE: MOVEB / MOVEDW not supported by SEC Era %d. SEC PC: %d; Instr: %d\n",
100 		       USER_SEC_ERA(rta_sec_era), program->current_pc,
101 		       program->current_instruction);
102 		goto err;
103 	}
104 
105 	/* write command type */
106 	if (cmd_type == __MOVEB) {
107 		opcode = CMD_MOVEB;
108 	} else if (cmd_type == __MOVEDW) {
109 		opcode = CMD_MOVEDW;
110 	} else if (!(flags & IMMED)) {
111 		if (rta_sec_era < RTA_SEC_ERA_3) {
112 			pr_err("MOVE: MOVE_LEN not supported by SEC Era %d. SEC PC: %d; Instr: %d\n",
113 			       USER_SEC_ERA(rta_sec_era), program->current_pc,
114 			       program->current_instruction);
115 			goto err;
116 		}
117 
118 		if ((length != MATH0) && (length != MATH1) &&
119 		    (length != MATH2) && (length != MATH3)) {
120 			pr_err("MOVE: MOVE_LEN length must be MATH[0-3]. SEC PC: %d; Instr: %d\n",
121 			       program->current_pc,
122 			       program->current_instruction);
123 			goto err;
124 		}
125 
126 		opcode = CMD_MOVE_LEN;
127 		is_move_len_cmd = true;
128 	} else {
129 		opcode = CMD_MOVE;
130 	}
131 
132 	/* write offset first, to check for invalid combinations or incorrect
133 	 * offset values sooner; decide which offset should be here
134 	 * (src or dst)
135 	 */
136 	ret = set_move_offset(program, src, src_offset, dst, dst_offset,
137 			      &offset, &opt);
138 	if (ret < 0)
139 		goto err;
140 
141 	opcode |= (offset << MOVE_OFFSET_SHIFT) & MOVE_OFFSET_MASK;
142 
143 	/* set AUX field if required */
144 	if (opt == MOVE_SET_AUX_SRC) {
145 		opcode |= ((src_offset / 16) << MOVE_AUX_SHIFT) & MOVE_AUX_MASK;
146 	} else if (opt == MOVE_SET_AUX_DST) {
147 		opcode |= ((dst_offset / 16) << MOVE_AUX_SHIFT) & MOVE_AUX_MASK;
148 	} else if (opt == MOVE_SET_AUX_LS) {
149 		opcode |= MOVE_AUX_LS;
150 	} else if (opt & MOVE_SET_AUX_MATH) {
151 		if (opt & MOVE_SET_AUX_SRC)
152 			offset = src_offset;
153 		else
154 			offset = dst_offset;
155 
156 		if (rta_sec_era < RTA_SEC_ERA_6) {
157 			if (offset)
158 				pr_debug("MOVE: Offset not supported by SEC Era %d. SEC PC: %d; Instr: %d\n",
159 					 USER_SEC_ERA(rta_sec_era),
160 					 program->current_pc,
161 					 program->current_instruction);
162 			/* nothing to do for offset = 0 */
163 		} else {
164 			ret = math_offset(offset);
165 			if (ret < 0) {
166 				pr_err("MOVE: Invalid offset in MATH register. SEC PC: %d; Instr: %d\n",
167 				       program->current_pc,
168 				       program->current_instruction);
169 				goto err;
170 			}
171 
172 			opcode |= (uint32_t)ret;
173 		}
174 	}
175 
176 	/* write source field */
177 	ret = __rta_map_opcode((uint32_t)src, move_src_table,
178 			       move_src_table_sz[rta_sec_era], &val);
179 	if (ret < 0) {
180 		pr_err("MOVE: Invalid SRC. SEC PC: %d; Instr: %d\n",
181 		       program->current_pc, program->current_instruction);
182 		goto err;
183 	}
184 	opcode |= val;
185 
186 	/* write destination field */
187 	ret = __rta_map_opcode((uint32_t)dst, move_dst_table,
188 			       move_dst_table_sz[rta_sec_era], &val);
189 	if (ret < 0) {
190 		pr_err("MOVE: Invalid DST. SEC PC: %d; Instr: %d\n",
191 		       program->current_pc, program->current_instruction);
192 		goto err;
193 	}
194 	opcode |= val;
195 
196 	/* write flags */
197 	if (flags & (FLUSH1 | FLUSH2))
198 		opcode |= MOVE_AUX_MS;
199 	if (flags & (LAST2 | LAST1))
200 		opcode |= MOVE_AUX_LS;
201 	if (flags & WAITCOMP)
202 		opcode |= MOVE_WAITCOMP;
203 
204 	if (!is_move_len_cmd) {
205 		/* write length */
206 		if (opt == MOVE_SET_LEN_16b)
207 			opcode |= (length & (MOVE_OFFSET_MASK | MOVE_LEN_MASK));
208 		else
209 			opcode |= (length & MOVE_LEN_MASK);
210 	} else {
211 		/* write mrsel */
212 		switch (length) {
213 		case (MATH0):
214 			/*
215 			 * opcode |= MOVELEN_MRSEL_MATH0;
216 			 * MOVELEN_MRSEL_MATH0 is 0
217 			 */
218 			break;
219 		case (MATH1):
220 			opcode |= MOVELEN_MRSEL_MATH1;
221 			break;
222 		case (MATH2):
223 			opcode |= MOVELEN_MRSEL_MATH2;
224 			break;
225 		case (MATH3):
226 			opcode |= MOVELEN_MRSEL_MATH3;
227 			break;
228 		}
229 
230 		/* write size */
231 		if (rta_sec_era >= RTA_SEC_ERA_7) {
232 			if (flags & SIZE_WORD)
233 				opcode |= MOVELEN_SIZE_WORD;
234 			else if (flags & SIZE_BYTE)
235 				opcode |= MOVELEN_SIZE_BYTE;
236 			else if (flags & SIZE_DWORD)
237 				opcode |= MOVELEN_SIZE_DWORD;
238 		}
239 	}
240 
241 	__rta_out32(program, opcode);
242 	program->current_instruction++;
243 
244 	return (int)start_pc;
245 
246  err:
247 	program->first_error_pc = start_pc;
248 	program->current_instruction++;
249 	return ret;
250 }
251 
252 static inline int
253 set_move_offset(struct program *program __maybe_unused,
254 		uint64_t src, uint16_t src_offset,
255 		uint64_t dst, uint16_t dst_offset,
256 		uint16_t *offset, uint16_t *opt)
257 {
258 	switch (src) {
259 	case (CONTEXT1):
260 	case (CONTEXT2):
261 		if (dst == DESCBUF) {
262 			*opt = MOVE_SET_AUX_SRC;
263 			*offset = dst_offset;
264 		} else if ((dst == KEY1) || (dst == KEY2)) {
265 			if ((src_offset) && (dst_offset)) {
266 				pr_err("MOVE: Bad offset. SEC PC: %d; Instr: %d\n",
267 				       program->current_pc,
268 				       program->current_instruction);
269 				goto err;
270 			}
271 			if (dst_offset) {
272 				*opt = MOVE_SET_AUX_LS;
273 				*offset = dst_offset;
274 			} else {
275 				*offset = src_offset;
276 			}
277 		} else {
278 			if ((dst == MATH0) || (dst == MATH1) ||
279 			    (dst == MATH2) || (dst == MATH3)) {
280 				*opt = MOVE_SET_AUX_MATH_DST;
281 			} else if (((dst == OFIFO) || (dst == ALTSOURCE)) &&
282 			    (src_offset % 4)) {
283 				pr_err("MOVE: Bad offset alignment. SEC PC: %d; Instr: %d\n",
284 				       program->current_pc,
285 				       program->current_instruction);
286 				goto err;
287 			}
288 
289 			*offset = src_offset;
290 		}
291 		break;
292 
293 	case (OFIFO):
294 		if (dst == OFIFO) {
295 			pr_err("MOVE: Invalid DST. SEC PC: %d; Instr: %d\n",
296 			       program->current_pc,
297 			       program->current_instruction);
298 			goto err;
299 		}
300 		if (((dst == IFIFOAB1) || (dst == IFIFOAB2) ||
301 		     (dst == IFIFO) || (dst == PKA)) &&
302 		    (src_offset || dst_offset)) {
303 			pr_err("MOVE: Offset should be zero. SEC PC: %d; Instr: %d\n",
304 			       program->current_pc,
305 			       program->current_instruction);
306 			goto err;
307 		}
308 		*offset = dst_offset;
309 		break;
310 
311 	case (DESCBUF):
312 		if ((dst == CONTEXT1) || (dst == CONTEXT2)) {
313 			*opt = MOVE_SET_AUX_DST;
314 		} else if ((dst == MATH0) || (dst == MATH1) ||
315 			   (dst == MATH2) || (dst == MATH3)) {
316 			*opt = MOVE_SET_AUX_MATH_DST;
317 		} else if (dst == DESCBUF) {
318 			pr_err("MOVE: Invalid DST. SEC PC: %d; Instr: %d\n",
319 			       program->current_pc,
320 			       program->current_instruction);
321 			goto err;
322 		} else if (((dst == OFIFO) || (dst == ALTSOURCE)) &&
323 		    (src_offset % 4)) {
324 			pr_err("MOVE: Invalid offset alignment. SEC PC: %d; Instr %d\n",
325 			       program->current_pc,
326 			       program->current_instruction);
327 			goto err;
328 		}
329 
330 		*offset = src_offset;
331 		break;
332 
333 	case (MATH0):
334 	case (MATH1):
335 	case (MATH2):
336 	case (MATH3):
337 		if ((dst == OFIFO) || (dst == ALTSOURCE)) {
338 			if (src_offset % 4) {
339 				pr_err("MOVE: Bad offset alignment. SEC PC: %d; Instr: %d\n",
340 				       program->current_pc,
341 				       program->current_instruction);
342 				goto err;
343 			}
344 			*offset = src_offset;
345 		} else if ((dst == IFIFOAB1) || (dst == IFIFOAB2) ||
346 			   (dst == IFIFO) || (dst == PKA)) {
347 			*offset = src_offset;
348 		} else {
349 			*offset = dst_offset;
350 
351 			/*
352 			 * This condition is basically the negation of:
353 			 * dst in { CONTEXT[1-2], MATH[0-3] }
354 			 */
355 			if ((dst != KEY1) && (dst != KEY2))
356 				*opt = MOVE_SET_AUX_MATH_SRC;
357 		}
358 		break;
359 
360 	case (IFIFOABD):
361 	case (IFIFOAB1):
362 	case (IFIFOAB2):
363 	case (ABD):
364 	case (AB1):
365 	case (AB2):
366 		if ((dst == IFIFOAB1) || (dst == IFIFOAB2) ||
367 		    (dst == IFIFO) || (dst == PKA) || (dst == ALTSOURCE)) {
368 			pr_err("MOVE: Bad DST. SEC PC: %d; Instr: %d\n",
369 			       program->current_pc,
370 			       program->current_instruction);
371 			goto err;
372 		} else {
373 			if (dst == OFIFO) {
374 				*opt = MOVE_SET_LEN_16b;
375 			} else {
376 				if (dst_offset % 4) {
377 					pr_err("MOVE: Bad offset alignment. SEC PC: %d; Instr: %d\n",
378 					       program->current_pc,
379 					       program->current_instruction);
380 					goto err;
381 				}
382 				*offset = dst_offset;
383 			}
384 		}
385 		break;
386 	default:
387 		break;
388 	}
389 
390 	return 0;
391  err:
392 	return -EINVAL;
393 }
394 
395 static inline int
396 math_offset(uint16_t offset)
397 {
398 	switch (offset) {
399 	case 0:
400 		return 0;
401 	case 4:
402 		return MOVE_AUX_LS;
403 	case 6:
404 		return MOVE_AUX_MS;
405 	case 7:
406 		return MOVE_AUX_LS | MOVE_AUX_MS;
407 	}
408 
409 	return -EINVAL;
410 }
411 
412 #endif /* __RTA_MOVE_CMD_H__ */
413