xref: /dpdk/drivers/common/dpaax/caamflib/rta/move_cmd.h (revision 882f25383499f422dc36cfd96ea688a92fb47d94)
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
rta_move(struct program * program,int cmd_type,uint64_t src,uint16_t src_offset,uint64_t dst,uint16_t dst_offset,uint32_t length,uint32_t flags)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 	/* write command type */
99 	if (cmd_type == __MOVEB) {
100 		opcode = CMD_MOVEB;
101 	} else if (cmd_type == __MOVEDW) {
102 		opcode = CMD_MOVEDW;
103 	} else if (!(flags & IMMED)) {
104 		if ((length != MATH0) && (length != MATH1) &&
105 		    (length != MATH2) && (length != MATH3)) {
106 			pr_err("MOVE: MOVE_LEN length must be MATH[0-3]. SEC PC: %d; Instr: %d\n",
107 			       program->current_pc,
108 			       program->current_instruction);
109 			goto err;
110 		}
111 
112 		opcode = CMD_MOVE_LEN;
113 		is_move_len_cmd = true;
114 	} else {
115 		opcode = CMD_MOVE;
116 	}
117 
118 	/* write offset first, to check for invalid combinations or incorrect
119 	 * offset values sooner; decide which offset should be here
120 	 * (src or dst)
121 	 */
122 	ret = set_move_offset(program, src, src_offset, dst, dst_offset,
123 			      &offset, &opt);
124 	if (ret < 0)
125 		goto err;
126 
127 	opcode |= (offset << MOVE_OFFSET_SHIFT) & MOVE_OFFSET_MASK;
128 
129 	/* set AUX field if required */
130 	if (opt == MOVE_SET_AUX_SRC) {
131 		opcode |= ((src_offset / 16) << MOVE_AUX_SHIFT) & MOVE_AUX_MASK;
132 	} else if (opt == MOVE_SET_AUX_DST) {
133 		opcode |= ((dst_offset / 16) << MOVE_AUX_SHIFT) & MOVE_AUX_MASK;
134 	} else if (opt == MOVE_SET_AUX_LS) {
135 		opcode |= MOVE_AUX_LS;
136 	} else if (opt & MOVE_SET_AUX_MATH) {
137 		if (opt & MOVE_SET_AUX_SRC)
138 			offset = src_offset;
139 		else
140 			offset = dst_offset;
141 
142 		ret = math_offset(offset);
143 		if (ret < 0) {
144 			pr_err("MOVE: Invalid offset in MATH register. SEC PC: %d; Instr: %d\n",
145 			       program->current_pc,
146 			       program->current_instruction);
147 			goto err;
148 		}
149 
150 		opcode |= (uint32_t)ret;
151 	}
152 
153 	/* write source field */
154 	ret = __rta_map_opcode((uint32_t)src, move_src_table,
155 			       move_src_table_sz[rta_sec_era], &val);
156 	if (ret < 0) {
157 		pr_err("MOVE: Invalid SRC. SEC PC: %d; Instr: %d\n",
158 		       program->current_pc, program->current_instruction);
159 		goto err;
160 	}
161 	opcode |= val;
162 
163 	/* write destination field */
164 	ret = __rta_map_opcode((uint32_t)dst, move_dst_table,
165 			       move_dst_table_sz[rta_sec_era], &val);
166 	if (ret < 0) {
167 		pr_err("MOVE: Invalid DST. SEC PC: %d; Instr: %d\n",
168 		       program->current_pc, program->current_instruction);
169 		goto err;
170 	}
171 	opcode |= val;
172 
173 	/* write flags */
174 	if (flags & (FLUSH1 | FLUSH2))
175 		opcode |= MOVE_AUX_MS;
176 	if (flags & (LAST2 | LAST1))
177 		opcode |= MOVE_AUX_LS;
178 	if (flags & WAITCOMP)
179 		opcode |= MOVE_WAITCOMP;
180 
181 	if (!is_move_len_cmd) {
182 		/* write length */
183 		if (opt == MOVE_SET_LEN_16b)
184 			opcode |= (length & (MOVE_OFFSET_MASK | MOVE_LEN_MASK));
185 		else
186 			opcode |= (length & MOVE_LEN_MASK);
187 	} else {
188 		/* write mrsel */
189 		switch (length) {
190 		case (MATH0):
191 			/*
192 			 * opcode |= MOVELEN_MRSEL_MATH0;
193 			 * MOVELEN_MRSEL_MATH0 is 0
194 			 */
195 			break;
196 		case (MATH1):
197 			opcode |= MOVELEN_MRSEL_MATH1;
198 			break;
199 		case (MATH2):
200 			opcode |= MOVELEN_MRSEL_MATH2;
201 			break;
202 		case (MATH3):
203 			opcode |= MOVELEN_MRSEL_MATH3;
204 			break;
205 		}
206 
207 		/* write size */
208 		if (rta_sec_era >= RTA_SEC_ERA_7) {
209 			if (flags & SIZE_WORD)
210 				opcode |= MOVELEN_SIZE_WORD;
211 			else if (flags & SIZE_BYTE)
212 				opcode |= MOVELEN_SIZE_BYTE;
213 			else if (flags & SIZE_DWORD)
214 				opcode |= MOVELEN_SIZE_DWORD;
215 		}
216 	}
217 
218 	__rta_out32(program, opcode);
219 	program->current_instruction++;
220 
221 	return (int)start_pc;
222 
223  err:
224 	program->first_error_pc = start_pc;
225 	program->current_instruction++;
226 	return ret;
227 }
228 
229 static inline int
set_move_offset(struct program * program __maybe_unused,uint64_t src,uint16_t src_offset,uint64_t dst,uint16_t dst_offset,uint16_t * offset,uint16_t * opt)230 set_move_offset(struct program *program __maybe_unused,
231 		uint64_t src, uint16_t src_offset,
232 		uint64_t dst, uint16_t dst_offset,
233 		uint16_t *offset, uint16_t *opt)
234 {
235 	switch (src) {
236 	case (CONTEXT1):
237 	case (CONTEXT2):
238 		if (dst == DESCBUF) {
239 			*opt = MOVE_SET_AUX_SRC;
240 			*offset = dst_offset;
241 		} else if ((dst == KEY1) || (dst == KEY2)) {
242 			if ((src_offset) && (dst_offset)) {
243 				pr_err("MOVE: Bad offset. SEC PC: %d; Instr: %d\n",
244 				       program->current_pc,
245 				       program->current_instruction);
246 				goto err;
247 			}
248 			if (dst_offset) {
249 				*opt = MOVE_SET_AUX_LS;
250 				*offset = dst_offset;
251 			} else {
252 				*offset = src_offset;
253 			}
254 		} else {
255 			if ((dst == MATH0) || (dst == MATH1) ||
256 			    (dst == MATH2) || (dst == MATH3)) {
257 				*opt = MOVE_SET_AUX_MATH_DST;
258 			} else if (((dst == OFIFO) || (dst == ALTSOURCE)) &&
259 			    (src_offset % 4)) {
260 				pr_err("MOVE: Bad offset alignment. SEC PC: %d; Instr: %d\n",
261 				       program->current_pc,
262 				       program->current_instruction);
263 				goto err;
264 			}
265 
266 			*offset = src_offset;
267 		}
268 		break;
269 
270 	case (OFIFO):
271 		if (dst == OFIFO) {
272 			pr_err("MOVE: Invalid DST. SEC PC: %d; Instr: %d\n",
273 			       program->current_pc,
274 			       program->current_instruction);
275 			goto err;
276 		}
277 		if (((dst == IFIFOAB1) || (dst == IFIFOAB2) ||
278 		     (dst == IFIFO) || (dst == PKA)) &&
279 		    (src_offset || dst_offset)) {
280 			pr_err("MOVE: Offset should be zero. SEC PC: %d; Instr: %d\n",
281 			       program->current_pc,
282 			       program->current_instruction);
283 			goto err;
284 		}
285 		*offset = dst_offset;
286 		break;
287 
288 	case (DESCBUF):
289 		if ((dst == CONTEXT1) || (dst == CONTEXT2)) {
290 			*opt = MOVE_SET_AUX_DST;
291 		} else if ((dst == MATH0) || (dst == MATH1) ||
292 			   (dst == MATH2) || (dst == MATH3)) {
293 			*opt = MOVE_SET_AUX_MATH_DST;
294 		} else if (dst == DESCBUF) {
295 			pr_err("MOVE: Invalid DST. SEC PC: %d; Instr: %d\n",
296 			       program->current_pc,
297 			       program->current_instruction);
298 			goto err;
299 		} else if (((dst == OFIFO) || (dst == ALTSOURCE)) &&
300 		    (src_offset % 4)) {
301 			pr_err("MOVE: Invalid offset alignment. SEC PC: %d; Instr %d\n",
302 			       program->current_pc,
303 			       program->current_instruction);
304 			goto err;
305 		}
306 
307 		*offset = src_offset;
308 		break;
309 
310 	case (MATH0):
311 	case (MATH1):
312 	case (MATH2):
313 	case (MATH3):
314 		if ((dst == OFIFO) || (dst == ALTSOURCE)) {
315 			if (src_offset % 4) {
316 				pr_err("MOVE: Bad offset alignment. SEC PC: %d; Instr: %d\n",
317 				       program->current_pc,
318 				       program->current_instruction);
319 				goto err;
320 			}
321 			*offset = src_offset;
322 		} else if ((dst == IFIFOAB1) || (dst == IFIFOAB2) ||
323 			   (dst == IFIFO) || (dst == PKA)) {
324 			*offset = src_offset;
325 		} else {
326 			*offset = dst_offset;
327 
328 			/*
329 			 * This condition is basically the negation of:
330 			 * dst in { CONTEXT[1-2], MATH[0-3] }
331 			 */
332 			if ((dst != KEY1) && (dst != KEY2))
333 				*opt = MOVE_SET_AUX_MATH_SRC;
334 		}
335 		break;
336 
337 	case (IFIFOABD):
338 	case (IFIFOAB1):
339 	case (IFIFOAB2):
340 	case (ABD):
341 	case (AB1):
342 	case (AB2):
343 		if ((dst == IFIFOAB1) || (dst == IFIFOAB2) ||
344 		    (dst == IFIFO) || (dst == PKA) || (dst == ALTSOURCE)) {
345 			pr_err("MOVE: Bad DST. SEC PC: %d; Instr: %d\n",
346 			       program->current_pc,
347 			       program->current_instruction);
348 			goto err;
349 		} else {
350 			if (dst == OFIFO) {
351 				*opt = MOVE_SET_LEN_16b;
352 			} else {
353 				if (dst_offset % 4) {
354 					pr_err("MOVE: Bad offset alignment. SEC PC: %d; Instr: %d\n",
355 					       program->current_pc,
356 					       program->current_instruction);
357 					goto err;
358 				}
359 				*offset = dst_offset;
360 			}
361 		}
362 		break;
363 	default:
364 		break;
365 	}
366 
367 	return 0;
368  err:
369 	return -EINVAL;
370 }
371 
372 static inline int
math_offset(uint16_t offset)373 math_offset(uint16_t offset)
374 {
375 	switch (offset) {
376 	case 0:
377 		return 0;
378 	case 4:
379 		return MOVE_AUX_LS;
380 	case 6:
381 		return MOVE_AUX_MS;
382 	case 7:
383 		return MOVE_AUX_LS | MOVE_AUX_MS;
384 	}
385 
386 	return -EINVAL;
387 }
388 
389 #endif /* __RTA_MOVE_CMD_H__ */
390